我应该让 AsyncTask 成为 LiveData 或 Repository 的成员 class - 作为 Loader 的替代品
Should I make AsyncTask member of LiveData or Repository class - As replacement of Loader
LiveData
/ViewModel
可以很好地替代复杂的 Loader
.
AsyncTask
是 LiveData
的成员。
public class JsonLiveData extends LiveData<List<String>> {
public JsonLiveData(Context context) {
loadData();
}
private void loadData() {
new AsyncTask<Void,Void,List<String>>() {
}.execute();
}
}
但是,基于presentation from Lyla Fujiwara:
我应该让 AsyncTask
成为 Repository
class 的成员吗?
你应该在 LiveData
中避免 运行 你的 AsyncTask
。 LiveData
真的应该只关心数据的观察。不是更改数据的行为。
处理这种情况的最佳方法是使用 ViewModel
/ 存储库模式。
Activity / Fragment
从 ViewModel
观察 LiveData,ViewModel
从 Repository 观察 LiveData
。在存储库中进行了更改,这些更改被推送到其 LiveData
。这些更改将传递给 Activity / Fragment
(通过 ViewModel
)。
我会避免在这种情况下使用 AsyncTask。 AsyncTask 的好处是你可以在完成工作后在 UI 线程上获得结果。但在这种情况下,这不是必需的。 LiveData 会为您做到这一点。
这是一个(未经测试的)示例:
Activity
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();
}
}
视图模型
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;
}
}
存储库
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();
}
}
LiveData
/ViewModel
可以很好地替代复杂的 Loader
.
AsyncTask
是 LiveData
的成员。
public class JsonLiveData extends LiveData<List<String>> {
public JsonLiveData(Context context) {
loadData();
}
private void loadData() {
new AsyncTask<Void,Void,List<String>>() {
}.execute();
}
}
但是,基于presentation from Lyla Fujiwara:
我应该让 AsyncTask
成为 Repository
class 的成员吗?
你应该在 LiveData
中避免 运行 你的 AsyncTask
。 LiveData
真的应该只关心数据的观察。不是更改数据的行为。
处理这种情况的最佳方法是使用 ViewModel
/ 存储库模式。
Activity / Fragment
从 ViewModel
观察 LiveData,ViewModel
从 Repository 观察 LiveData
。在存储库中进行了更改,这些更改被推送到其 LiveData
。这些更改将传递给 Activity / Fragment
(通过 ViewModel
)。
我会避免在这种情况下使用 AsyncTask。 AsyncTask 的好处是你可以在完成工作后在 UI 线程上获得结果。但在这种情况下,这不是必需的。 LiveData 会为您做到这一点。
这是一个(未经测试的)示例:
Activity
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();
}
}
视图模型
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;
}
}
存储库
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();
}
}