【问题标题】:Android AsyncTask RecyclerView does not populateAndroid AsyncTask RecyclerView 不填充
【发布时间】:2018-03-21 09:25:28
【问题描述】:

我想制作一个应用程序列表应用程序,它通过包管理器通过嵌套在单例类中的AsyncTask<Void, Void, List<PackageSummary>> 获取应用程序列表。但是,当且仅当我实现异步任务时,RecyclerView 不会在第一个 OnCreate 上填充。

我确信我犯了一个愚蠢的错误和/或对 AsyncTask 和 RecyclerView 的理解不够好,但是为了我的爱,我找不到问题的根源。

In my toy app repository我准备了两个比较干净的分支,用于说明:

  • 在主线程中获取包,并在第一个 Oncreate (git_UI_thread) 上填充 recyclerview。
  • 其中调用了AsyncTask<Void, Void, List<PackageSummary>> 类。应用程序持久性尚未设置(故意),RecyclerView 只会在应用程序旋转后填充(git_background_thread)。

对于不喜欢点击上面bitbucket链接的朋友,我的AsyncTask里面的代码sn-p是这样的:

    @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;
}

P.S.:我认为(但不确定)单例模式是合理的,以减少内存泄漏的变化。

P.S.2:我已经阅读了几个关于此的问题,但没有一个可以接受/有效的解决方案。

【问题讨论】:

  • 您在何时何地执行异步任务?

标签: java android android-asynctask android-recyclerview


【解决方案1】:

有两个步骤:将您的数据更新到 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();
    }

【讨论】:

  • 这将导致我需要将 RecyclerView.Adapter 对象传递给 Singleton。此外,应用程序列表是 RecyclerView.Adapter 的构造函数中的一个参数。无论哪种方式,即使我可以让它工作,它也不能真正帮助清洁代码。还是我不是很了解?
  • 这是一种使其工作的肮脏方式。在这种情况下,一个干净的代码是使用观察者设计模式
  • 我的谷歌技能似乎不足以为这种模式找到一个好的指南(除了数据绑定和黄油刀)。可以给我一个链接吗?
  • 你可以在这里找到一个例子:stackoverflow.com/questions/42983101/…我的建议是使用纯Java(不是Android)来实现一个简单的先了解它
【解决方案2】:

只需在 AsyncTaskpostexecute 方法中添加 adapter.notifyDataSetChanged();

【讨论】:

    【解决方案3】:

    要么我无法实现观察者模式(请注意,asynctask 位于与 recyclerview 和活动分开的单例类中),要么在这种情况下无法正常工作。

    无论如何,我最终用相对较新的lifecycle-aware components 解决了这个问题: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);
        });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-06
      • 1970-01-01
      • 2018-08-23
      • 2018-07-18
      • 2018-03-25
      • 1970-01-01
      • 1970-01-01
      • 2020-02-11
      相关资源
      最近更新 更多