热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android从UI线程而不是后台线程修改适配器

我有一个用json填充并使用自定义适配器的ListView。这是我在ZoznamActivity中缩短的代码:

我有一个用json填充并使用自定义适配器的ListView。

这是我在Zoznamactivity中缩短的代码:

public class Zoznam extends AppCompatactivity{
private ArrayList actorsList;
private actorAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_filter);
final ListView lv = findViewById(R.id.listView1);
actorsList = new ArrayList<>();
adapter = new actorAdapter(this,"Zoznam",actorsList);
lv.setadapter(adapter);adapter.notifyDataSetChanged();
new getcontacts(Zoznam.this).execute("all","all");
private static class getcontacts extends AsyncTask {
ProgressDialog dialog;
private final WeakReference activityReference;
getcontacts(Zoznam context) {
activityReference = new WeakReference<>(context);
}
@Override
protected void onPreExecute() {
Zoznam activity = activityReference.get();
if (activity == null || activity.isFinishing()) return;
super.onPreExecute();
dialog = new ProgressDialog(activity);
dialog.setMessage(activity.getResources().getString(R.string.Loading));
dialog.setTitle(activity.getResources().getString(R.string.connecting));
dialog.show();
dialog.setCancelable(false);
}
@Override
protected String doInBackground(String... sText1) {final Zoznam activity = activityReference.get();
HttpHandler sh = new HttpHandler();
String url = "URL";
String jsOnStr= sh.makeServiceCall(url);
if (jsonStr != null) {
try {JSONObject jsOnObj= new JSONObject(jsonStr);
JSONArray actors = jsonObj.getJSONArray("result");
for (int i = 0; i JSONObject c = actors.getJSONObject(i);
actors actor = new actors();
actor.setLetter(c.getString("letter"));
actor.setNazov(c.getString("nazov"));
actor.setThumb(c.getString("thumb"));
activityReference.get().actorsList.add(actor);
}
} catch (final JSONException e) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity,R.string.Nodata,Toast.LENGTH_LONG).show();
}
}); }
return jsonStr;
} else {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity,R.string.Network,Toast.LENGTH_LONG).show();
}
});
return null;
}
}
protected void onPostExecute(String result) {
Zoznam activity = activityReference.get();
if (activity == null || activity.isFinishing()) return;
dialog.dismiss();
activity.adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
}
protected void onResume() {
super.onResume();
adapter.notifyDataSetChanged();
}

问题是,在崩溃报告中我发现了此错误:

适配器的内容已更改,但ListView没有收到通知。确保不从后台线程修改适配器的内容,而仅从UI线程修改。确保您的适配器在其内容更改时调用notifyDataSetChanged()。

但是,仅在一台设备上发生了一次,但是我想解决此问题。

我已经阅读了更多关于此的主题,但是我仍然没有解决方案。正如您在我的代码中看到的那样,我也在onPostExecute上调用notifyDataSetChanged(),所以不确定问题出在哪里。


您可能得到了例外,因为您在后台线程上更新了适配器列表。

activityReference.get().actorsList.add(actor); doInBackground方法中的这一行正在更新您传递给适配器的实际列表。 doInBackground中的所有这些计算必须非常快地进行,并且来自notifyDataSetChanged的{​​{1}}被调用。我不确定如何,但是这一次没有及时调用您的onPostExecute,因此您的列表已更新,但是您的onPostExecute没有收到通知。

您可以在ListView中创建本地列表,并在AsyncTask中更新活动的列表。示例代码-

onPostExecute

这应该可以,但是您可以通过使用回调进一步改进代码。这样,您将不必在asyncTask内保留活动的引用,并且可以将所有逻辑移出asyncTask。 https://stackoverflow.com/a/15693380/6168272这个答案应该很有帮助。

,

更改AsyncTask,以便计算doInBackground()中的列表,然后将其返回到onPostExecute(),然后在那里进行所有更新:

// change the type parameters to return a List
private static class GetContacts extends AsyncTask> {
@Override
protected List doInBackground(Void... ignored) {
// add this at the top
List actors = new ArrayList<>();
// inside your loop,replace this line:
// activityReference.get().actorsList.add(actor);
// with this instead
actors.add(actor);
// and at the end,return the list
return actors;
}
// the list you returned from doInBackground() is passed here
protected void onPostExecute(List result) {
// update your activity all at once in this method
activity.actorsList.clear();
activity.actorsList.addAll(result);
activity.adapter.notifyDataSetChanged();
}
}

我整理了一些代码以使内容更易于阅读,但总的思路就在那里。


推荐阅读
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • React项目中运用React技巧解决实际问题的总结
    本文总结了在React项目中如何运用React技巧解决一些实际问题,包括取消请求和页面卸载的关联,利用useEffect和AbortController等技术实现请求的取消。文章中的代码是简化后的例子,但思想是相通的。 ... [详细]
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 图像因存在错误而无法显示 ... [详细]
  • 本文介绍了一款名为TimeSelector的Android日期时间选择器,采用了Material Design风格,可以在Android Studio中通过gradle添加依赖来使用,也可以在Eclipse中下载源码使用。文章详细介绍了TimeSelector的构造方法和参数说明,以及如何使用回调函数来处理选取时间后的操作。同时还提供了示例代码和可选的起始时间和结束时间设置。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
author-avatar
炙天痕_953
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有