我的应用程序上出现错误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
并更新onPostExecute()
AsyncTask
方法上的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);
}
});
}
答案 0 :(得分:3)
您的主线程可能很慢,因为您正在运行包含许多对象的循环。但是,不知道你究竟在执行什么,这只是猜测。
但是我的AsyncTask存在问题,我认为它不适用于您发布的代码。
AsyncTask期待一系列URL。你没有通过任何。如果不需要URL作为输入,那么只需使用:
AsyncTask task = new AsyncTask<Void, Boolean, Boolean>()
您尝试进行问题排查:
AsyncTask task = new AsyncTask<URL, Boolean, Boolean>() {
@Override
protected Boolean 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 true;
}
@Override
protected void onPostExecute(Boolean result) {
if(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);
}
}
}
};
然后通过触发执行任务:
URL[] urls = new URL[2];
urls[0] = new URL(...);
urls[1] = new URL(...);
task.execute(urls);
使用IDE中的调试功能,如果代码失败,则回发确切的位置。
答案 1 :(得分:1)
您没有在您创建的AsyncTask上调用execute(),因此永远不会被触发。
在创建AsyncTask之后,在其上调用execute(URL ... params)以便它将被执行。
此外,我发现你没有使用你传递的参数,所以你可以不通过它,它会起作用。
答案 2 :(得分:1)
您最好在IntentService上进行网络请求。它很容易并且防止界面冻结和/或“应用程序可能在其主线程上做了太多工作”。
看看:
答案 3 :(得分:1)
在你的代码中你正在调用AsynTast,你应该调用一次for:for each循环应该在doinbackground()内部和onProgressUpdate()中你可以更新UI而不是onPostExecute(),这稍微改进代码但不完全,你应该在onPreexecute上使用进度条并在onPostEcecute()中关闭进度条,只是为了你的想法我写了下面的代码,但是没有完全引用它,因为我还没有测试过这个,但形成这个会有所了解。
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().equals("Public") && application.getPublicAdapter().containsId(publicPosts, post.getId()) == null) {
application.getPublicAdapter().getPosts().add(0, post);
}
publishProgress((1);
}
return null;
}
@Override
protected void onProgressUpdate(Integer... progress) {
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);
}
}
}
@Override
protected void onPostExecute(Long result) {
}
}
};
答案 4 :(得分:1)
如果你创建了一个扩展AsyncTask的类并在你的ondatachange方法中调用它,它会更清晰,更容易维护:
import
通过这种方式,您可以在工作线程中安全地执行Firebase连接,并使用您检索到的结果更新UI。
答案 5 :(得分:0)
您可以尝试以下某些操作:
答案 6 :(得分:0)
建议:
2.当其他线程完成繁重的工作时,如果需要更新UI,请使用Handler将msg发送到UI主线程,然后在主线程上更新UI。