我有一个使用Fragment和View寻呼机的应用。我查询android联系人数据库(这应该很快),以获得在ListView中显示的每个联系人的主要数字。问题是,这似乎需要一些时间。我试图在onCreateView中使用一个Thread和一个ASyncTask并“更新”或为我的联系人列表设置我的适配器。当我这样做时,我遇到了一些错误:
无法在未调用Looper.prepare()
的线程内创建处理程序
我尝试使用Looper.prepare()但它仍会崩溃。
所以我放入了一个处理程序,但是当人们启动我的应用程序时存在延迟
final Runnable setupView = new Runnable() {
@Override
public void run() {
contactos = con.getContactSearch("");
setupContacts();
}
};
其中: getContactSearch:
public HashMap<String, ContactInfo> getContactSearch(String _where)
{
contactInfo = new HashMap<String, ContactInfo>();
Cursor cursor = null ;
if(_where.length()==0)
{
cursor = getContacts();
}else
{
cursor = getContactsFilter(_where);
}
try
{
while (cursor.moveToNext()) {
String id = cursor.getString(cursor
.getColumnIndex(ContactsContract.Contacts._ID));
if(!contactInfo.containsKey(id))
{
String displayName = cursor.getString(cursor
.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
//obtenemos el telefono principal
//String number = "" ;//getPrimaryNumber(id);
ContactInfo ci = new ContactInfo(displayName,"",id);
contactInfo.put(id,ci);
}
}
getPrimaryNumbers();
}finally
{
cursor.close();
}
return contactInfo;
}
和setupcontacts:
mAdapter = new DialerContactsAdapter(contactos,getActivity());
listaContactos.setAdapter(mAdapter);
listaContactos.setFastScrollEnabled(true);
listaContactos.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case OnScrollListener.SCROLL_STATE_IDLE:
mAdapter.mBusy = false;
mAdapter.notifyDataSetChanged();
break;
case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
mAdapter.mBusy = false;
mAdapter.notifyDataSetChanged();
break;
case OnScrollListener.SCROLL_STATE_FLING:
mAdapter.mBusy = true;
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
});
我是如何异步执行此操作的?我想知道我是否只在onCreate()中搜索联系人会发生什么,如果它比onCreateView更快,ListView将为null。这样做“有效”,但存在很大的滞后。 我如何优化这个过程?
答案 0 :(得分:2)
你的setupContacts()方法摆弄了UI的东西,你不能在UI线程之外做。您必须创建一个新的Runnable并将其发布到UI线程视图Activity.runOnUiThread()或View.post()。
如果这看起来像是刺激性的样板,那就是。创建AsyncTask的目的是简化这种在后台执行操作的模型,然后发布到UI线程。
使用AsyncTasks的一个问题是,在任务完成时,启动它的Activity可能已经死了。如果是配置更改(例如设备轮换),您仍然需要数据,但是asynctask指向死引用。最好的情况是,没有任何反应,你得到一个空指针异常。这真是令人沮丧,因为Fragments可以在这些配置更改中幸存下来。
AnsyncTaskLoader是为了解决这个问题而创建的。 API文档中有一个AsyncTaskLoader示例,它在获取一些数据后填充适配器。