I keep getting an error on my application that says I/Choreographer: Skipped 252 frames! The application may be doing too much work on its main thread.
I think this causes some lag on my UI which I don't want. I think it is because when I perform a Firebase query, when I do onDataChange()
, it seems to be always executed in the main UI Thread. I have around 5 Firebase queries similar to what I have below. As a result, I tried to move my code from onDataChange()
method to an AsyncTask
and update the UI thread on onPostExecute()
method of AsyncTask
. However, when I try this, the onPostExecute()
method never completes. Here is my attempt:
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) {
}
});
}
Any help with this would be helpful. If anyone could help me out that would be great. Thanks!
EDIT: Adding in Function to create 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 function:
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);
}
});
}
Your main thread is probably slow because you are running a loop with many objects. However, not knowing what exactly you are executing, that is just a guess.
But I a problem with your AsyncTask, I don't think it will ever work with the code you posted.
The AsyncTask is expecting an array of URLs. You are not passing any. If don't need URLs as input, then just use:
AsyncTask task = new AsyncTask<Void, Boolean, Boolean>()
How about you try for troubleshooting:
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);
}
}
}
};
Then execute the task by firing:
URL[] urls = new URL[2];
urls[0] = new URL(...);
urls[1] = new URL(...);
task.execute(urls);
Use the debug feature in the IDE and post back the exact place if the code fails.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With