Search code examples
javaandroidandroid-asynctask

Choreographer skipping frames(upto 400!) even after using AsyncTask


I am trying to get data from my remote server, trying to create a database in SQLite and updating my shared preferences. I have placed all of the previous mentioned operations in an AsyncTask which theoretically must be running on a separate thread other than the UI (main)thread. Also, I am running the application on an actual Android device and not an emulator.

I am getting the following info in the logs:

I/Choreographer: Skipped 229 frames!  The application may be doing too much work on its main thread.

Source code:

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.ExecutionException;

public class MainActivity extends AppCompatActivity {

    TextView errorMessage;
    Button retryAgainButton;

    SharedPreferences sharedPrefs;

    @SuppressLint("StaticFieldLeak")
    public class FirstRunDBCreator extends AsyncTask<Void, Void, String> {
        String result = "";
        private Exception e = null;

        @Override
        protected void onPreExecute() {
            sharedPrefs = getApplicationContext().getSharedPreferences("android.content.SharedPreference", Context.MODE_PRIVATE);
            if(!sharedPrefs.contains("firstRun")) {
                sharedPrefs.edit().putBoolean("firstRun", true).apply();
            }
        }

        @Override
        protected String doInBackground(Void... voids) {
            String result = "";
            // All the heavy operations here
            // Fetching the data from the server here and creating/ storing data in my SQLite database
            // I have also used transactions and SQLite preparedStatement to increase the insert speed
            return result;
        }

        @SuppressLint("SetTextI18n")
        @Override
        protected void onPostExecute(String s) {
            // Closing the database connections and handling any exceptions here
            // Updating the UI elements such as diplaying the complete message or the visibility of a textview
        }
    }

    public void initializeTheUIComponents() {
        errorMessage = findViewById(R.id.errorMessage);
        retryAgainButton = findViewById(R.id.retryAgainButton);
        retryAgainButton.setClickable(false);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initializeTheUIComponents();
        // Running the jumpToNextActivity after the screen and the UI elements have been rendered
        getWindow().getDecorView().post(new Runnable() {
            @Override
            public void run() {
                try {
                    new FirstRunDBCreator().execute().get();
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

Although, I don't have any high res images or any heavy front end components apart from two TextViews and the fact that all of the heavy processing is being carried out in the background thread, what is causing the choreographer to skip the frames? Is it because that I am calling the AsyncTask in the onCreate() method or because I have some piece of code in the onPreExecute() or onPostExecute()? Is it the Runnable run() Or any other reason for that matter?


Solution

  • when you call .get() method, it will operate on the current thread which is the UI thread in this case so try executing without get.