android - 我应该让 LiveData 或 Repository 类的 AsyncTask 成员 - 作为 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();
}
}
然而,根据Lyla Fujiwara 的介绍:
我应该成为班级AsyncTask
成员吗?Repository
解决方案
你应该避免运行你AsyncTask
的LiveData
. LiveData
真的应该只关心数据的观察。不是更改数据的行为。
处理这种情况的最好方法是使用ViewModel
/Repository 模式。
Activity / Fragment
从 观察 LiveData ViewModel
,从 RepositoryViewModel
观察。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();
}
}
视图模型
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();
}
}
推荐阅读
- java - synchronized 关键字如何作用于实例变量?
- python - 在 Pandas 数据框中使用多索引进行数据透视
- javascript - 如何计算给定(x,y,z)磁力计和加速度计数据的航向(N / W / S / E)?
- sql - 如何正确索引具有 2500 万行的 SQL Server 表
- java - MySql 日期一日拆分
- python-3.x - 在python中将数据框行转换为没有列索引的值字符串
- ios - 如何返回异步json请求的结果
- c++ - Converting mysqlx::Value to std::string with special characters
- azure - Azure 表存储错误请求 - 查询语法错误
- apache-kafka - 有人用过 Apache Kafka 的 CNCF CloudEvent 吗?