我应该让AsyncTask成为LiveData还是Repository类的成员-作为Loader的替换

Che*_*eng 2 android android-livedata android-architecture-components android-jetpack

LiveData/ ViewModel是复杂的很好的替代品Loader

基于https://medium.com/google-developers/lifecycle-aware-data-loading-with-android-architecture-components-f95484159de4

AsyncTask是的成员LiveData

public class JsonLiveData extends LiveData<List<String>> {

  public JsonLiveData(Context context) {

    loadData();
  }


  private void loadData() {
    new AsyncTask<Void,Void,List<String>>() {

    }.execute();
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,根据Lyla Fujiwara演讲

在此处输入图片说明

我应该成为班级AsyncTask成员Repository吗?

Kno*_*sos 6

您应该避免运行你AsyncTaskLiveDataLiveData真正应该只关注数据的观察。不是更改数据的行为。

处理这种情况的最佳方法是使用ViewModel/存储库模式。

Activity / Fragment从中观察LiveData ViewModel,从存储库中ViewModel观察LiveData。在存储库中进行更改,并将更改推送到其存储库中LiveData。这些更改将Activity / Fragment通过传递给ViewModel

在这种情况下,我将避免使用AsyncTask。AsyncTask的好处是您可以在完成工作后在UI线程上获得结果。但是在这种情况下,这不是必需的。LiveData将为您做到这一点。

这是一个(未经测试的)示例:

活动

public class MyActivity extends AppCompatActivity {

    private MyViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Set up your view model
        viewModel = ViewModelProviders.of(this).get(MyViewModel.class);

        // Observe the view model
        viewModel.getMyLiveData().observe(this, s -> {
            // You work with the data provided through the view model here.
            // You should only really be delivering UI updates at this point. Updating
            // a RecyclerView for example.
            Log.v("LIVEDATA", "The livedata changed: "+s);
        });

        // This will start the off-the-UI-thread work that we want to perform.
        MyRepository.getInstance().doSomeStuff();
    }
}
Run Code Online (Sandbox Code Playgroud)

视图模型

public class MyViewModel extends AndroidViewModel {

    @NonNull
    private MyRepository repo = MyRepository.getInstance();

    @NonNull
    private LiveData<String> myLiveData;

    public MyViewModel(@NonNull Application application) {
        super(application);
        // The local live data needs to reference the repository live data
        myLiveData = repo.getMyLiveData();
    }

    @NonNull
    public LiveData<String> getMyLiveData() {
        return myLiveData;
    }
}
Run Code Online (Sandbox Code Playgroud)

资料库

public class MyRepository {

    private static MyRepository instance;

    // Note the use of MutableLiveData, this allows changes to be made
    @NonNull
    private MutableLiveData<String> myLiveData = new MutableLiveData<>();

    public static MyRepository getInstance() {
        if(instance == null) {
            synchronized (MyRepository.class) {
                if(instance == null) {
                    instance = new MyRepository();
                }
            }
        }
        return instance;
    }

    // The getter upcasts to LiveData, this ensures that only the repository can cause a change
    @NonNull
    public LiveData<String> getMyLiveData() {
        return myLiveData;
    }

    // This method runs some work for 3 seconds. It then posts a status update to the live data.
    // This would effectively be the "doInBackground" method from AsyncTask.
    public void doSomeStuff() {
        new Thread(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException ignored) {
            }

            myLiveData.postValue("Updated time: "+System.currentTimeMillis());
        }).start();
    }

}
Run Code Online (Sandbox Code Playgroud)