【发布时间】:2016-09-28 16:02:47
【问题描述】:
我的应用程序不断收到错误消息,上面写着 I/Choreographer: Skipped 252 frames! The application may be doing too much work on its main thread. 我认为这会导致我的 UI 出现一些我不想要的延迟。我认为这是因为当我执行 Firebase 查询时,当我执行 onDataChange() 时,它似乎总是在主 UI 线程中执行。我有大约 5 个与下面类似的 Firebase 查询。结果,我尝试将我的代码从onDataChange() 方法移动到AsyncTask 并更新AsyncTask 的onPostExecute() 方法上的UI 线程。但是,当我尝试这个时,onPostExecute() 方法永远不会完成。这是我的尝试:
public void getPublicPosts(final View progressOverlay, final View fragmentView, final Context context) {
//Need to do order by / equal to.
Firebase postsRef = firebaseRef.child("Posts");
Query query = postsRef.orderByChild("privacy").equalTo("Public");
query.keepSynced(true);
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (final DataSnapshot postSnapShot : dataSnapshot.getChildren()) {
AsyncTask task = new AsyncTask<URL, Integer, Long>() {
@Override
protected Long doInBackground(URL... params) {
Post post = postSnapShot.getValue(Post.class);
List<Post> publicPosts = application.getPublicAdapter().getPosts();
if (post.getPrivacy().equals("Public") && application.getPublicAdapter().containsId(publicPosts, post.getId()) == null) {
application.getPublicAdapter().getPosts().add(0, post);
}
return null;
}
@Override
protected void onProgressUpdate(Integer... progress) {
}
@Override
protected void onPostExecute(Long result) {
System.out.println("Finished executing public");
populateNewsFeedList(fragmentView, application.getPublicAdapter(), TabEnum.Public, context);
if (progressOverlay.getVisibility() == View.VISIBLE) {
System.out.println("getPublicPosts: DONE");
AndroidUtils.animateView(progressOverlay, View.GONE, 0, 200);
fragmentView.findViewById(R.id.rv_public_feed).setVisibility(View.VISIBLE);
}
}
};
`task.execute();`
}
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
对此的任何帮助都会有所帮助。如果有人可以帮助我,那就太好了。谢谢!
编辑:添加函数以创建AsyncTask
public AsyncTask asyncTaskWrapper(final DataSnapshot dataSnapshot, final View progressOverlay, final View fragmentView, final Context context) {
AsyncTask task = new AsyncTask<URL, Integer, Long>() {
@Override
protected Long doInBackground(URL... params) {
for (final DataSnapshot postSnapShot : dataSnapshot.getChildren()) {
Post post = postSnapShot.getValue(Post.class);
List<Post> publicPosts = application.getPublicAdapter().getPosts();
if (post.getPrivacy() == PrivacyEnum.Public && application.getPublicAdapter().containsId(publicPosts, post.getId()) == null) {
application.getPublicAdapter().getPosts().add(0, post);
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... progress) {
}
@Override
protected void onPostExecute(Long result) {
System.out.println("Finished executing public");
TabsUtil.populateNewsFeedList(fragmentView, application.getPublicAdapter(), TabEnum.Public, context);
if (progressOverlay.getVisibility() == View.VISIBLE) {
System.out.println("getPublicPosts: GONE");
AndroidUtils.animateView(progressOverlay, View.GONE, 0, 200);
fragmentView.findViewById(R.id.rv_public_feed).setVisibility(View.VISIBLE);
}
}
};
return task;
}
PublicPosts 功能:
public void getPublicPosts(final View progressOverlay, final View fragmentView, final Context context) {
//Need to do order by / equal to.
Firebase postsRef = firebaseRef.child("Posts");
Query query = postsRef.orderByChild("privacy").equalTo(PrivacyEnum.Public.toString());
query.keepSynced(true);
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
asyncTaskWrapper(dataSnapshot, progressOverlay, fragmentView, context);
}
@Override
public void onCancelled(FirebaseError firebaseError) {
TabsUtil.populateNewsFeedList(fragmentView, application.getPublicAdapter(), TabEnum.Public, context);
}
});
}
【问题讨论】:
-
不是在for循环中实现AsyncTask,而是单独定义它,然后从for循环中执行,这样它就可以安全地运行在另一个线程上。
-
@Vickyexpert 嗨,我明白你想说什么,但我似乎无法找到一种方法来实例化
AsyncTask一次而不重新创建多次。我已经在原帖中发布了我的尝试。 -
什么是application.getPublicAdapter()??我认为跳帧的一个原因可能是 application.getPublicAdapter().getPosts().add(0, post) 多次触发 notifyDataSetChanged。这也可能是您的应用程序退出的原因,因为无法在后台线程中调用 notifyDataSetChanged。
-
¿ 有必要在主线程中显示进度吗?我认为 Asynctask 仅在 doInBackground() 函数的后台执行。因此,它将是更高效的线程和处理程序系统。
标签: java android multithreading android-asynctask firebase