请我阅读很多东西,因为我读了不同的意见和不同的方法,我感到很困惑.
问题如下:
在AdapterI的getView()中,需要执行一些异步操作,比如检查Web上的格式,并基于此更新视图.
我使用了以下方法:
每次调用getView()时我都会启动一个Thread
但我的做法为我赢得了很多批评:
https://stackoverflow.com/a/28484345/1815311
https://stackoverflow.com/a/28484335/1815311
https://stackoverflow.com/a/28484351/1815311
public View getView(int position,View convertView,ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
//...
}
else {
//...
}
Thread th= new Thread(new Runnable() {
@Override
public void run() {
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
CheckSomeInfoOverTheInternet(url,new myCallback {
@Override
public void onSuccess() {
holder.textview.setText("OK");
}
@Override
public void onFailre() {
holder.textview.setText("NOT OK!!!!");
}
});
}
});
}
});
th.start();
return convertView;
}
请问做这样事情的最佳做法是什么?
请注意,我不是在寻找在getView()中执行网络请求的解决方案,而是如何根据异步调用的结果更新视图.
解决方法
虽然你在做什么真的不合适.
> AsyncTask
>此处的线程池是在内部完成的,因此您无需为此烦恼
>它可以更清晰地解决您的问题而不是产生单个线程.
>如果您的用户在API通话期间更改了屏幕,您也可以使用cancel the call.
>您必须启用notifyDatasetChanged()
>您需要覆盖很少的函数来实现所需的功能.
> AsyncTaskLoader
>它为您提供了更多控制权,但您却失去了几个隐式定义的函数
>你需要更多的知识来使用它,并且应该精通像LoaderManager,Loader这样的类.
>改变就是自我改变
假设您要更改基础数据集,更改将自动触发并提供对UI的更改.
> Handlers和线程
>这比你当前的appraoch高出一个但是提供了更多的好处
>您可以抽象线程创建并提供处理所有id的调用的处理程序.
>您可以对线程和传递的消息进行排队.
>如果屏幕改变,你可以remove callbacks and messages.
总之,您当前方法的主要缺点是:
– 需要进行更改时丢失上下文.
– 显式创建多个线程
虽然后者是一个主要问题,但首先是“用户更明显”的问题.
基于您需要的控件以及您在Android回调和线程管理方面的专业知识,可能还有其他几种方法.但这三种方法(据我所知)最合适.
PS:所有这些方法的共同点是,
public View getView(int position,ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
//...
}
else {
//...
}
//execute a task for your given id where task Could be:
//1. AsyncTask
//2. AsyncTaskLoader
//3. Handlers and thread
//call notifyDataSetChanged() in all the cases,return convertView;
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
//do any tasks which you feel are required
}
PPS:您还可以查看DataSetObserver以再次自动化您的要求.