[英]NullPointerException with android AsyncTask and RecyclerView
[英]Android AsyncTask RecyclerView does not populate
我想制作一個應用程序列表器應用程序,該應用程序通過嵌套在單例類中的AsyncTask<Void, Void, List<PackageSummary>>
通過packagemanager獲取應用程序列表。 但是,當且僅當我實現異步任務時,RecyclerView才會在第一個OnCreate上填充。
我確定我犯了一個愚蠢的錯誤,並且/或者對AsyncTask和RecyclerView的理解不夠好,但是出於對我的愛,我找不到問題的根源。
在我的玩具應用程序存儲庫中,我准備了兩個相對較干凈的分支用於說明目的:
AsyncTask<Void, Void, List<PackageSummary>>
類。 應用程序持久性尚未設置(有意),並且RecyclerView
僅在旋轉應用程序之后填充( git_background_thread )。 對於那些不想單擊上面的bitbucket鏈接的人,我的AsyncTask
內部的代碼段如下所示:
@Override
protected void onPostExecute(List<SingletonPackageSummarySupplier.PackageSummary> packageSummaries) {
super.onPostExecute(packageSummaries);
isQueryingInProgress = false;
packageSummaryList = packageSummaries;
}
@Override
protected List<SingletonPackageSummarySupplier.PackageSummary> doInBackground(Void... voids) {
List<PackageSummary> installedPackages = new ArrayList<>();
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
List<ResolveInfo> resolveInfoList = context.getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo resolveInfo : resolveInfoList) {
ActivityInfo activityInfo = resolveInfo.activityInfo;
installedPackages.add(new PackageSummary(resolveInfo.activityInfo));
}
return installedPackages;
}
這是我的主要活動OnCreate:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
psList = SingletonPackageSummarySupplier.getInstance(context).getPackageSummaryListReadOnly();
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerViewLayoutManager = new LinearLayoutManager(context);
recyclerView.setLayoutManager(recyclerViewLayoutManager);
adapter = new AdapterApplist(context, psList);
recyclerView.setAdapter(adapter);
}
這是獲取單例的方式:
static SingletonPackageSummarySupplier instance;
public static SingletonPackageSummarySupplier getInstance(Context context) {
if (instance == null) {
instance = new SingletonPackageSummarySupplier(context);
} else{
instance.updateInstance(context);
}
return instance;
}
PS:我認為(但不確定)單例模式是合理的,以便減少內存泄漏的變化。
PS2:我已經閱讀了幾個有關此問題,但沒有一個解決方案可以接受。
只需添加adapter.notifyDataSetChanged();
在您的AsyncTask
的postexecute
方法中
分兩個步驟:將數據更新到AdapterApplist並通知它。 因此,您應該創建一個新方法,例如:
public void setData(List<SingletonPackageSummarySupplier.PackageSummary> list)
{ //reset your data ere
}
在AdapterApplist類中。 然后,更新您的帖子:
@Override
protected void onPostExecute(List<SingletonPackageSummarySupplier.PackageSummary> packageSummaries) {
super.onPostExecute(packageSummaries);
isQueryingInProgress = false;
packageSummaryList = packageSummaries;
adapter.setData(packageSummaryList);
adapter.notifyDataSetChanged();
}
我要么無法實現觀察者模式(請注意asynctask位於與recyclerview和activity分開的單例類中),要么在這種情況下無法正常工作。
無論如何,我最終使用相對較新的可感知生命周期的組件來解決該問題:MutableLiveData,LiveData和AndroidViewModel(而不是不會將上下文作為構造函數參數的viewmodel)。 簡單而優雅。
在活動中,關鍵部分是這樣的:
PackageSummarySupplier model = ViewModelProviders.of(this).get(PackageSummarySupplier.class);
model.getPackageSummaryList().observe(this, packageSummaryList -> {
adapter = new AdapterApplist(context, packageSummaryList);
recyclerView.setAdapter(adapter);
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.