Android-将数据从AsyncTask传递到Activity



我正试图将一个字符串从AsyncTask传递回我的"活动"。浏览其他类似的问题(例如这里(,我决定使用一个界面监听器。

接口:

package com.example.myapplication;
public interface GetListener {
void passJSONGet(String s);
}

AsyncTask类:

package com.example.myapplication;
import android.content.Context;
import android.os.AsyncTask;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

public class DataGetter extends AsyncTask<String, Void, String> {
Context context;
private GetListener GetListener;
public String jsonString;
DataGetter(Context ctx, GetListener listener) {
this.context = ctx;
this.GetListener = listener;
}
@Override
protected String doInBackground(String... params) {
String ip = params[0];
String scriptname = params[1];
String db = params[2];
String urladress = "http://" + ip + "/"+ scriptname +".php";
try {
URL url = new URL(urladress);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
OutputStream os = connection.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(os, "UTF-8");
String data = URLEncoder.encode("database", "UTF-8") + "=" + URLEncoder.encode(db, "UTF-8");
writer.write(data);
writer.flush();
writer.close();
BufferedReader reader = new BufferedReader(new
InputStreamReader(connection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
break;
}
return sb.toString();
} catch (Exception e) {
return e.getMessage();
}
}
@Override
protected void onPostExecute(String result) {
GetListener.passJSONGet(result);
}
}

我的活动:

import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import org.json.JSONArray;
import org.json.JSONException;

public class WeatherDisplay extends AppCompatActivity implements GetListener {
private JSONArray jsonArray;
private String jsonString;
@Override
protected void onCreate(Bundle savedInstanceState) {

// other code

DataGetter dataGetter = new DataGetter(this, WeatherDisplay.this);
dataGetter.execute(ip, "readLatestOutside", "weather");
Toast.makeText(this, this.jsonString, Toast.LENGTH_LONG).show();
this.jsonArray = new JSONArray(this.jsonString);
// furter code
}
@Override
public void passJSONGet(String jsonstring) {
this.jsonString = jsonstring;
}

JSON是从服务器正确获取的,通常在onPostExecute中可见,但稍后在WeatherDisplay中不可见(Toast显示为空,变量仍然是空指针(。

如何解决此问题?我缺乏经验,可能会错过一些琐碎的事情。

我认为对Android如何运行您的代码进行一点解释可能会有所帮助。

因此,在后台,Android正在无休止地运行一些代码。该循环的一部分是检查消息队列,它基本上是任务传递的地方——它需要执行的代码。理想情况下,它将足够快地完成每个循环中所需的所有工作,每秒可以管理60个循环。如果它有太多的事情要做,那就是它开始放慢速度并感到刺耳的地方。

一些可能被执行的任务就像正在创建的Activity,所以它可能希望系统运行其onCreate代码——每个Activity会运行一次。你可能已经注意到它只发生过一次,这就是你无休止循环的地方,对吧?把执行困在那里,直到AsyncTask交付结果?

问题是你正在阻止主循环工作——在完成任务之前,它无法继续前进并做任何事情,而你是故意阻止它的。总的来说,这是非常糟糕的,这就是为什么我们鼓励你不要在主线程(运行主活套的线程(上进行缓慢的操作——它会产生耗时太长的工作,并降低整个UI的响应速度(UI处理也是需要运行的任务(

一般来说,这很糟糕,但AsyncTask的实际工作方式是它们在另一个线程上运行(所以它们不会阻塞主线程,这就像让另一个独立的人处理东西一样(,但它们在主线程上交付结果。他们向主线程的消息队列发布一条消息,告诉它运行onPostExecute代码。

但是,在处理完队列中的早期任务之前,系统无法获取该消息。如果它忙于运行一个无休止的循环来等待AsyncTask的结果,它将永远不会收到该消息,变量将永远不会更新,循环也永远不会看到它正在等待的更改。这就像有人在排队,拒绝移动,直到他们看到有人在后面试图交付


这是一堆背景,但关键是你永远不应该阻止这样的线程,除非它是你创建的一个特殊线程,这样你就知道它是可以的,不会干扰其他任何事情。把Android更多地想象成一个事件驱动的系统——你编写的代码应该在发生什么事情时执行,比如创建活动(ònCreate(、按下按钮(onClick(或AsyncTask完成时(onPostExecute(。所有这些方法都以";上"quot;当一件事发生时,这样做">

因此,当您的任务完成时,它将运行onPostExecute,这就是处理接收结果的所有代码的位置。它实际上不需要在onPostExecute方法中——就像你把你的方法放在passJSONGet方法中以保持组织一样,但它是从onPostExecute调用的,这是触发正在运行的代码的事件。

因此,无论你需要对结果做什么,都可以从onPostExecute调用它。当这种情况发生时,它会做你让它做的事情。更新一个变量,做一个toast,用一些新数据填充布局中的视图,等等!

将代码更改为:

@Override
protected void onCreate(Bundle savedInstanceState) {

// other code

DataGetter dataGetter = new DataGetter(this, WeatherDisplay.this);
dataGetter.execute(ip, "readLatestOutside", "weather");

// furter code
}
@Override
public void passJSONGet(String jsonstring) {
this.jsonString = jsonstring;
this.jsonArray = new JSONArray(this.jsonString);
Toast.makeText(this, this.jsonString, Toast.LENGTH_LONG).show();

}

你的流量不对。所有UI工作都应该在onPostExecute 之后完成

相关内容

  • 没有找到相关文章

最新更新