gpt4 book ai didi

java - 在后台加载数据,更新适配器?

转载 作者:行者123 更新时间:2023-12-01 09:00:04 27 4
gpt4 key购买 nike

我使用 ArrayAdapter 来显示项目列表,并且我有一个 AsyncTask 线程通过 HttpURLConnection 加载这些项目。我希望这个项目列表成为用户启动应用程序时首先看到的东西。我知道让应用程序在启动时等待加载完成是不好的做法,这就是我将加载设为 AsyncTask 的原因。我将本地数据存储在 SharedPreferences 中,同时显示。

不幸的是,我无法直接从 AsyncTask 中修改适配器。

java.lang.IllegalStateException:确保适配器的内容不是从后台线程修改的,而是仅从 UI 线程修改的。

我想我只需要一个信号来通知 UI 线程后台任务已完成;我可以修改我的代码以将数据加载到不是适配器的另一个数据结构中,然后 UI 线程在知道任务完成后可以将其添加到适配器中。我不知道如何在不等待 AsyncTask 完成的情况下执行此操作,这与我在主 UI 线程中等待数据加载相同。

我该怎么办?

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
...
LoadAnnouncementDataFromAPI announcementAPIQuery = new LoadAnnouncementDataFromAPI();
announcementAPIQuery.execute();
...
}

...

private class LoadAnnouncementDataFromAPI extends AsyncTask<String, String, String> {

private String announcementAPI = "http://10.0.2.2:3000/announcements";

@Override
protected String doInBackground(String... params) {
try {
URL url = new URL(announcementAPI);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));

StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
bufferedReader.close();
return stringBuilder.toString();
} catch (IOException e) {
return "";
}
}

@Override
protected void onPostExecute(String queryResponse) {
if (queryResponse != null && !queryResponse.equals("")) {
try {
JSONArray apiResponse = new JSONArray(queryResponse);
for (int i = 0; i < apiResponse.length(); i++) {
JSONObject announcementJSON = apiResponse.getJSONObject(i);
if (!announcementJSON.getString("id").equals("")) {
mAnnouncementAdapter.items.add(new AnnouncementBlock(announcementJSON));
}
}
mAnnouncementAdapter.notifyDataSetChanged();
} catch (JSONException e) {
return;
}
}
}
}
}

最佳答案

您只需向 asynTask 添加监听器即可做到这一点。当您收到回调时,请确保更新代码在 UI 线程上运行。

一些代码

1 - 回调接口(interface)

interface OnAddListener {
void onAdd (AnnouncementBlock announcementBlock);
}

2 - 改变你的类(class)

class LoadAnnouncementDataFromAPI extends AsyncTask<String,String,String> {
OnAddListener listener;

public void setOnAddListener(OnAddListener listener) {
this.listener = listener;
}

LoadAnnouncementDataFromAPI(OnAddListener listener) {
this.listener = listener;
// Or may be pass it to the constructor...
}

protected String doInBackground(String... params) {
// Your logic
// And then!
if(listener!=null){
listener.onAdd(new AnnouncementBlock(announcementJSON));
}
// ...
}
}

3 - 您可以从 Activity 中获取回调。我倾向于喜欢 Activity 直接实现接口(interface)的方法(可能是为了避免使用 final 关键字),但您也可以采用其他方式。

// Notice that the activity is implementing the OnAddListener interface.
class YourActivity extends Activity implements OnAddListener {

// ... Some logic life cycle callbacks

// I suppose you're doing something similar
private void startUpdating(){
mLoadAnnouncementDataFromAPI.setListener(this); // set the listener.
}

// Your callback.
@Override
public void onAdd(final AnnouncementBlock announcementBlock) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// Now you're sure it's running in the UI thread ;)
mAnnouncementAdapter.items.onAdd(announcementBlock);
}
});
}
}

关于java - 在后台加载数据,更新适配器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41752550/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com