我正在尝试使用JSON和PHP将我的应用程序连接到Mysql数据库。 PHP脚本返回一个JSON数组,用于确定灯的状态(true或false)。
我尝试将JSON代码放在单独的类中,该代码打开URL连接并获取状态。因此,每当我需要使用它时,我都可以调用它。
问题是变量res
在JSON类中确实有一个值,但是当我尝试使用JSON对象从主Activity访问它时,它是空的。任何人都可以指导我找到解决这个问题的正确解决方案吗?
主要活动
public class MainActivity extends AppCompatActivity {
public TextView t;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
t = (TextView) findViewById(R.id.t1);
Json j = new Json();
j.execute("http://127.0.0.1/web/test.php");
t.setText(j.res);
}
}
Json class
public class Json extends AsyncTask<String, String, String> {
String result = "";
public String res="";
@Override
protected void onPreExecute() {
}
@Override
protected String doInBackground(String... params) {
InputStream isr = null;
try {
String URL = params[0];
java.net.URL url = new URL(URL);
URLConnection urlConnection = url.openConnection();
isr = new BufferedInputStream(urlConnection.getInputStream());
} catch (Exception e) {
Log.e("log_tag", "error in http conection" + e.toString());
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(isr, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
isr.close();
result = sb.toString();
} catch (Exception e) {
Log.e("Log", "failed " + e.toString());
}
return null;
}
JSONObject json;
protected void onPostExecute(String result2) {
try {
String password1 = "";
JSONArray jArray = new JSONArray(result);
for (int i = 0; i < jArray.length(); i++) {
json = jArray.getJSONObject(i);
res=json.getString("status");
break;
}
} catch (Exception e) {
}
}
}
答案 0 :(得分:0)
您无法将AsyncTask 中的值返回到主线程。有两种可能的解决方案
1)将您的文字视图设为全局变量,并在AsyncTask
覆盖onPostExecute()
。在帖子执行中,您可以使用服务器中的数据更新文本视图。
2)制作一个监听器(接口)。您的活动应该实现它并再次覆盖onPostExecute()
并使用json数据调用该侦听器,最后在回调中使用json中的数据更新您的视图。
protected void onPostExecute(String result2) {
try {
String password1 = "";
JSONArray jArray = new JSONArray(result);
for (int i = 0; i < jArray.length(); i++) {
json = jArray.getJSONObject(i);
res=json.getString("status");
break;
}
// UPDATE your views here, or make a callback to your class
// via a listener and json data as a parameter and update
// your views there. Async tasks can cause memory leaks.
// Be careful with them.
} catch (Exception e) {
}
}
希望它有所帮助。
(PS - 只是一个提示,不要抓住一般例外,这是一个不好的做法)
此外,您可以将doInBackground
的字符串传递给onPostExecute
,该字符串由AsyncTask<String, String, String>
的第3个参数决定。因此,由于您告诉它该对象属于String
类型,您可以使用return null;
调用中生成的字符串doInBackground
替换null。
public class Json extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
}
@Override
protected String doInBackground(String... params) {
InputStream isr = null;
String result;
try {
String URL = params[0];
java.net.URL url = new URL(URL);
URLConnection urlConnection = url.openConnection();
isr = new BufferedInputStream(urlConnection.getInputStream());
} catch (Exception e) {
Log.e("log_tag", "error in http conection" + e.toString());
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(isr, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
isr.close();
result = sb.toString();
} catch (Exception e) {
Log.e("Log", "failed " + e.toString());
}
return result;
}
JSONObject json;
protected void onPostExecute(String result) {
try {
String password1 = "";
JSONArray jArray = new JSONArray(result);
for (int i = 0; i < jArray.length(); i++) {
json = jArray.getJSONObject(i);
res=json.getString("status");
break;
}
} catch (JSONArrayException ignored) {
}
}
}
我没有运行此代码。也许你可以检查和验证!
答案 1 :(得分:0)
执行是在另一个线程中,如果要在不在Json类中的活动中使用您重写t.setText(j.res);
的活动中的结果,则可以在执行请求之前执行行onpostExecute
如下:
new Json(){
@Override
protected void onPostExecute(String result2) {
//use string result as you want here
}
}.execute("http://127.0.0.1/web/test.php");
并在doInBackGround
中返回结果。不归null