2014-02-01 4 views
0

Как говорится в названии, я начинаю с Loader нажатием кнопки, а затем меняю ориентацию. В воссозданной деятельности onLoadFinished не вызывается автоматически при запуске. Мое подозрение состоит в том, что LoaderManager не имеет представления об этом недавно созданном экземпляре активности, поскольку я не думаю, что это связано с жизненным циклом активности. Но я могу ошибаться ...Android-загрузчик начался с щелчка, а затем изменилась ориентация - данные больше не предоставлены

Это загрузчик, предоставляющий массив строк и имитирующий его затягивание данных с помощью 3 секунд. Реализация представляет собой упрощенную версию AsyncTaskLoadersample code.

import android.content.Context; 
import android.support.v4.content.AsyncTaskLoader; 

public class ContentAsyncLoader extends AsyncTaskLoader<String[]> { 
    private String[] data; 

    public ContentAsyncLoader(Context context) { 
     super(context); 
    } 

    @Override 
    protected void onStartLoading() { 
     if (data != null) { 
      deliverResult(data); 
     } else { 
      forceLoad(); 
     } 
    } 

    @Override 
    public String[] loadInBackground() { 
     synchronized (this) { 
      try { 
       wait(3000); 
      } catch (InterruptedException e) { 
      } 
     } 
     final String[] result = { "Dell Inspiron", "HTC One X", "HTC Wildfire S", "HTC Sense", "HTC Sensation XE", "iPhone 4S", "Samsung Galaxy Note 800", "Samsung Galaxy S3", "MacBook Air", 
       "Mac Mini", "MacBook Pro" }; 
     return result; 
    } 

    @Override 
    protected void onStopLoading() { 
     cancelLoad(); 
    } 

    @Override 
    protected void onReset() { 
     super.onReset(); 
     onStopLoading(); 
     data = null; 
    } 

    @Override 
    public void deliverResult(String[] data) { 
     if (isReset()) { 
      return; 
     } 
     this.data = data; 
     if (isStarted()) { 
      super.deliverResult(data); 
     } 
    } 
} 

И ниже деятельность, которая запускает загрузчик на кнопку мыши - это ListView и Button:

public class MainActivity extends FragmentActivity implements OnClickListener, LoaderCallbacks<String[]> { 

    private static final int LOADER_ID = 1; 
    private ListView lv; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     lv = (ListView) findViewById(R.id.list_view); 
     findViewById(R.id.btnSomeAction).setOnClickListener(this); 
    } 

    @Override 
    public void onClick(View v) { 
     getSupportLoaderManager().initLoader(LOADER_ID, null, this); 
    } 

    @Override 
    public Loader<String[]> onCreateLoader(int id, Bundle bundle) { 
     ContentAsyncLoader loader = new ContentAsyncLoader(this); 
     return loader; 
    } 

    @Override 
    public void onLoaderReset(Loader<String[]> loader) { 
    } 

    @Override 
    public void onLoadFinished(Loader<String[]> loader, String[] data) { 
     if (data != null) { 
      ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, data); 
      lv.setAdapter(adapter); 
     } 
    } 
} 

Если кто-то хочет четкий вопрос: как правильно сделать использование Loader что запускается нажатием кнопки, чтобы данные автоматически повторно предоставлялись при воссоздании активности?

У меня есть некоторые грязную работу вокруг, чтобы исправить это, держа флаг установлен в верно, когда кнопка нажата, сохранить его, когда onSaveInstanceState называется, а затем в onCreate проверить, если присутствует, и если это так назвать initLoader; но я не хочу иметь это в таких случаях, и когда я начинаю разные загрузчики от деятельности мне нужно держать флаг для каждого такого загрузчика, как я, как правило, ленив ... Например:

private boolean loaderCreated; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    lv = (ListView) findViewById(R.id.list_view); 
    findViewById(R.id.btnSomeAction).setOnClickListener(this); 
    if (savedInstanceState != null) { 
     loaderCreated = savedInstanceState.getBoolean("TEMP", false); 
     if(loaderCreated) { 
      getSupportLoaderManager().initLoader(LOADER_ID, null, this); 
     } 
    } 
} 

@Override 
protected void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    outState.putBoolean("TEMP", loaderCreated); 
} 

@Override 
public void onClick(View v) { 
    loaderCreated = true; 
    getSupportLoaderManager().initLoader(LOADER_ID, null, this); 
} 

Isn» Есть ли лучший способ сделать это?

ответ

2

getSupportLoaderManager().initLoader(LOADER_ID, null, this); следует называть onCreate каждый раз, если кнопка была нажата раньше.

Потому что теперь после ориентации savedInstanceState не является нулевым, и вы не спрашиваете загрузчика о данных.

И я вижу, что вы делаете это ...;), и это единственный путь.

С уважением

+0

Да, я знаю ... Но, как говорится, я ненавижу делать это каждый раз, не лучший способ сделать это? Почему «LoaderManager» не знает об этой воссозданной деятельности? – gunar

+1

LoaderManager ничего не знает. Это задание по работе, чтобы спросить о данных, и Activity должна спросить только, есть ли такая необходимость (что означает, что нажата кнопка). Вы не должны называть эту переменную 'loaderCreated', а' dataWasLoaded' или что-то вроде 'iWantToSeeData';), потому что реальная информация заключается в том, что вы хотите отображать данные, нажимая кнопку –

+0

Действительно, это единственный метод. Я бы любил, однако, что «LoaderManager» должен делать это от моего имени. – gunar