![](/img/trans.png)
[英]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.