我尝试将一个ArrayList从MainActivity中的AsyncTask传递到一个片段,但是我得到了一个调用CategoryAdapter.getItemCount()
的 NullPointerException,即使我在BroadCastReceiver调用之后传递数组也是如此。
我做错了什么?
主要活动
class GetBooksAsync extends AsyncTask<Void, Void, Void> {
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
@Override
protected Void doInBackground(Void... voids) {
for (ECategories category : ECategories.values()) {
try {
categories.add(new Category(category.toString(), apiClient.getBooks(category)));
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Intent intent = new Intent("com.android.mainapp");
intent.putExtra("categories", categories);
manager.sendBroadcast(intent);
replaceFragment(new HomeFragment());
}
}
家庭片段
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
initBroadCastReceiver();
categoryAdapter = new CategoryAdapter(categories,getContext());
View view = inflater.inflate(R.layout.fragment_home, container, false);
recyclerView = view.findViewById(R.id.parent_rv);
recyclerView.setAdapter(categoryAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
categoryAdapter.notifyDataSetChanged();
return view;
}
private void initBroadCastReceiver() {
manager = LocalBroadcastManager.getInstance(getContext());
MyBroadCastReceiver receiver = new MyBroadCastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.android.mainapp");
manager.registerReceiver(receiver,filter);
}
class MyBroadCastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//get the categories from the intent
categories = new ArrayList<Category>();
categories = (ArrayList<Category>) intent.getSerializableExtra("categories");
}
}
我也尝试过从OnReceive方法附加recyclerView,但是没有附加。提前感谢!
4条答案
按热度按时间ljo96ir51#
我认为你的代码有几个问题:
1.您的任务正在UIThread以外的线程中运行(调度任务并处理结果)。这意味着它很可能在不同的处理器/内核上运行。(例如您的集合)缓存在处理器中,并且在执行后的某个时间将数据写回RAM。但这可能发生在调用
onPostExecute
方法之后,这也会把这个集合带到另一个处理器缓存中。但是当这个过程在这个集合从任务返回到RAM之前完成时,它仍然是空的。这被称为竞态条件。现在有几种方法可以解决这个问题。最简单的方法是使用
Collections.synchronizedList(categories)
。这可以防止处理器缓存列表值,并始终将其返回到RAM(或使用所有处理器/内核共享的三级缓存)。1.我不确定你传递给集合的确切内容。Intent(以及它的数据)需要是可序列化的,而你添加到集合中的内容可能是不可序列化的。
然后使用
AsyncTask
参数:请注意,不建议使用
AsyncTask
和LocalBroadcastManager
。kkbh8khc2#
yr9zkbsy3#
我猜您将数据从
MainActivity
传递到HomeFragment
的方式不正确。您的期望
1.呼叫
MainActivity#GetBooksAsync
1.等待
onPostExecute
被调用HomeFragment
准备好接收广播消息,然后更新UI1.将消息从
MainActivity
广播到片段"这里发生了什么"
1.呼叫
MainActivity#GetBooksAsync
1.等待
onPostExecute
被调用1.从
MainActivity
广播消息。没有接收者接收此消息!HomeFragment
准备好接收广播消息,然后更新UI那么您应该如何传递数据?
有几种办法。
1.在UI组件之间广播数据,就像你做的那样。但是你需要注意组件的生命周期。也就是说,当你广播数据时,接收器必须已经初始化并且UI组件处于活动状态。
1.构建一个单例类来存储数据。您的Activity和片段将单例类视为数据存储的公共位置。
1.如果数据大小足够小,请使用Intent和extra属性传递数据。
1.使用LiveData。我相信这是社区推荐的最现代的方法。虽然我不知道它是如何工作的。
为了验证这是一个生命周期问题,
您可以尝试在发送广播留言之前添加延迟。
x4shl7ld4#
您的适配器应该这样编写。
您的片段应具有BroadcastReceiver的全局适配器以更新数据