2013-05-07 3 views
0

У меня есть приложение, использующее фрагмент с пейджером View. Я запрашиваю базу данных контактов Android (это должно быть быстро), чтобы получить первичные номера каждого контакта для показа в ListView. Проблема в том, что это, похоже, занимает некоторое время. Я попытался использовать Thread и ASyncTask внутри onCreateView и «обновить» или установить мой адаптер для моего списка контактов. Когда я делаю это я получаю некоторые ошибки:Темы внутри фрагмента

не может создать обработчик внутри потока, который не называется 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. Выполнение этого «работает», но есть большое отставание. Как я могу оптимизировать этот процесс?

+1

Используйте 'LoaderManager' для управления этим. Извлечение контактов внутри цикла всегда будет медленным. Если вы показываете какую-то информацию в составе ListView, а другие части строки выбираются быстрее, чем информация о контакте, я бы предложил вам лениво загружать более медленные части. – kishu27

ответ

2

Ваш setupContacts() метод скриптов с элементами UI, которые вы не можете сделать вне потока пользовательского интерфейса. Вам нужно будет создать новую Runnable и отправить ее в представление потока пользовательского интерфейса Activity.runOnUiThread() или View.post().

Если это похоже на раздражающий шаблон, это так. AsyncTask был создан с целью упростить эту модель работы в фоновом режиме и затем опубликовать ее в потоке пользовательского интерфейса.

Одна из проблем с использованием AsyncTasks заключается в том, что начавшаяся операция может быть мертвой к моменту завершения задачи. Если это было изменение конфигурации (например, поворот устройства), вам все равно нужны данные, но асинтеза указывает на мертвую ссылку. В лучшем случае ничего не происходит, в худшем случае вы получаете исключение с нулевым указателем. Это действительно разочаровывает, потому что Fragments может полностью пережить эти изменения конфигурации.

AnsyncTaskLoader был создан, чтобы иметь дело с этой проблемой. В документации API есть пример AsyncTaskLoader, который заполняет адаптер после извлечения некоторых данных.

+0

Ну, моя проблема, я думаю, использовал CUrsorLoader, im используя getcontentresolver теперь, возможно, я перемещаю все на Loader, и кажется, что это немного быстрее. :) Я использую этот сайт для использования AsynTaskLoader, потому что использование Loader сбивает с толку, это поможет http://www.androiddesignpatterns.com/2012/07/loaders- и-loadermanager-background.html – Javier