2013-06-03 2 views
6

Позвольте мне начать, сказав, что это НЕ вопрос о прокрутке ListViews. Я не хочу знать, как сказать, когда пользователь прокручивается до нижней части списка, поэтому, пожалуйста, не давайте мне ответов на этот вопрос или не отмечайте это как дубликат.Сообщите Android AsyncTaskLoader, чтобы получить больше данных

Я использую класс, который расширяет AsyncTaskLoader для заполнения ListView данными из веб-службы.

Первоначально, я загружаю 50 предметов и все отлично работает. Мне нужно знать, как сообщить загрузчику загружать следующие 50 элементов поэтапно. Я понимаю WHERE, чтобы сделать это в коде ListView, но Я не могу понять, как лучше сказать загрузчику, что я хочу загрузить больше данных, не перезагружая его и не загружая все снова.

Опять же, чтобы пояснить, проблема, которую я пытаюсь решить здесь, просто уведомляет загрузчика о необходимости загрузки большего количества данных. Он уже знает, как загружать больше данных, когда loadInBackground() вызывается во второй раз, и ListView уже знает, где/когда нужно уведомить загрузчика, вопрос только как.

Некоторые из соответствующего кода:

@Override 
public void onActivityCreated(Bundle savedInstanceState) 
{ 
    super.onActivityCreated(savedInstanceState); 

    m_adapter = new SearchAdapter(getActivity()); 
    setListAdapter(m_adapter); 

    // if the loader doesn't already exist, one will be created 
    // otherwise the existing loader is reused so we don't have 
    // to worry about orientation and other configuration changes 
    getLoaderManager().initLoader(SEARCH_LOADER_ID, null, this); 
} 

@Override 
public Loader<List<Result>> onCreateLoader(int id, Bundle args) 
{ 
    String query = args != null ? args.getString(QUERY_KEY) : ""; 
    return new SearchLoader(getActivity(), query); 
} 

private class SearchAdapter extends ArrayAdapter<Result> 
{ 
    // ... 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) 
    { 

     // ... 

     if (position == getCount() - 2) 
      // TODO: Need to notify Loader here 

     // ... 
    } 
} 

private static class SearchLoader extends OurAsyncTaskLoader<List<Result>> 
{ 
    public SearchLoader(Context context, String query) 
    { 
     super(context); 

     m_query = query; 
     m_data = Lists.newArrayList(); 
     m_loadedAllResults = false; 
    } 

    @Override 
    public List<Result> loadInBackground() 
    { 
     if (m_loadedAllResults) 
      return m_data; 

     // the Loader implementation does a == check rather than a .equals() check 
     // on the data, so we need this to be a new List so that it will know we have 
     // new data 
     m_data = Lists.newArrayList(m_data); 

     MyWebService service = new MyWebService(); 
     List<Result> results = service.getResults(m_query, m_data.size(), COUNT); 
     service.close(); 

     if (results == null) 
      return null; 

     if (results.size() < COUNT) 
      m_loadedAllResults = true; 

     for (Result result : results) 
      m_data.add(result) 

     return m_data; 
    } 

    private static final int COUNT = 50; 

    private final String m_query; 

    private boolean m_loadedAllResults; 
    private List<Result> m_data; 
} 
+0

@GeorgeStocker Пожалуйста, прочтите этот вопрос. Вы увидите, что это не дубликат вопроса, который вы указали. – drewhannay

+0

Необходимо загрузить дополнительные данные для одной и той же строки запроса? В любом случае я бы сбросил «Loader» и использовал «AsyncTask» или обычный поток для загрузки дополнительных данных. – Luksprog

+1

Но разве загрузчик не рекомендуется использовать для предоставления данных для возврата в ListView? AsyncTask не обрабатывает изменения конфигурации и Loaders. – drewhannay

ответ

3

Я выяснил способ, который работает. В моем SearchAdapter#getView() методе, у меня есть следующий код:

private class SearchAdapter extends ArrayAdapter<Result> 
{ 
    // ... 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) 
    { 

     // ... 

     if (position == getCount() - 2) 
      getLoaderManager().getLoader(SEARCH_LOADER_ID).onContentChanged(); 
     // ... 
    } 
} 

Я все еще хотел бы знать, если это «лучшая практика» способ сделать это, но мне кажется, чтобы решить мою проблему сейчас.

+0

Как вы получаете getLoaderManager() из вашего адаптера? – raybaybay

+0

My Adapter - внутренний класс внутри моего фрагмента – drewhannay

+0

Лучшие решения - самые простые – Bwire

0

В вашем сценарии я рекомендую использовать ForceLoadContentObserver, который вы можете связать с URI в ContentResolver. Как это:

class SearchLoader .... 
    ForceLoadContentObserver contentObserver = new ForceLoadContentObserver(); 
    .... 

    @Override 
    public void onStartLoading() { 
     if (cacheResult == null || takeContentChanged()) { // This will see if there's a change notification to observer and take it. 
      onForceLoad(); 
     } else { 
      deliverResult(cacheResult); 
     } 
    } 

    @Override 
    public Result loadInBackground() { 
     Result result = loadResult(); 
     // notification uri built upon Result.BASE_URI so it receives all notifications to BASE_URI. 
     getContext().getContentResolver().registerContentObserver(result.getNotificationUri(), true, contentObserver); 
    } 

    @Override 
    public void onReset() { 
     // ... Do your clean stuff... 
     getContext().getContentResolver().unregisterContentObserver(contentObserver); 
    } 

    ... 
} 

Таким образом, вы можете сообщить ваши изменения везде с помощью:

context.getContentResolver().notifyChanged(Result.BASE_URI, null); 

Даже когда активность держит загрузчик находится в фоновом режиме или нет возможности deliverResult. И вам не нужны экземпляры погрузчиков.

Все уведомления размещены вокруг объекта Uri. Uri является мощным представлением данных в Android.

Но у меня тоже есть путаница. В этом случае, как ваш подход, так и мой подход предполагает , изменение контента означает загрузку дополнительных данных. Но что делать, если вам нужно перезагрузить все данные? Какое уведомление вы будете использовать?

Смежные вопросы