0

我有一个使用带有视图寻呼机的片段的应用程序。我查询 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;
     }

和设置联系人:

    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 将为空。这样做“有效”,但有很大的滞后。我怎样才能优化这个过程?

4

1 回答 1

2

Your setupContacts() method fiddles with UI stuff, which you cannot do outside the UI thread. You'll have to create a new Runnable and post it to the UI thread view Activity.runOnUiThread() or View.post().

If this seems like irritating boilerplate, it is. AsyncTask was created with the intention to simplify this model of doing stuff in the background and then posting to the UI thread.

One problem with using AsyncTasks is that the Activity that started it may be dead by the time the task finishes. If it was a configuration change (e.g. device rotation), you'd still want the data, but the asynctask is pointing to a dead reference. At best nothing happens, at worst, you get a null pointer exception. This is really frustrating because Fragments can survive these configuration changes just fine.

AnsyncTaskLoader was created to deal with this problem. The API documentation has an example of an AsyncTaskLoader that populates an Adapter after fetching some data.

于 2013-05-07T19:04:40.467 回答