Domanda

I have an app that reads from an sqlite db in order to build the UI.

However, reading from sqlite is blocking and could possibly cause an ANR. What is the best practice to run UI-blocking code that is needed before the UI can be drawn?

È stato utile?

Soluzione

Use an AsyncTask https://developer.android.com/reference/android/os/AsyncTask.html

When you've completed your processing, use onPostExecute (Result result) to update your UI.

EDIT:

Just to elaborate, when you implement doInBackground (Params... params) in your AsyncTask, don't interact with your UI thread as that method is not executed on the UI thread.

If you need to update your UI, implement onPreExecute(), for updates before doing your background tasks, onProgressUpdate (Progress... values), for updates while doing background tasks, and/or onPostExecute (Result result), for when your AsyncTask completes doing its work. The "usage" section of the developer docs (from the link above) has a nice little example for onProgressUpdate (Progress... values)

EDIT 2:

Handling UI

It's good practice to show an (Indeterminate) progress bar while the AsyncTask is running.

An example layout XML is:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
    <!-- Use whichever style of progress bar you need, this one is a rotating circle and is indeterminate. Note, it is "gone" by default. The visibility toggle is handled by the AsyncTask -->
    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:indeterminate="true"
        android:visibility="gone" />

    <LinearLayout
        android:id="@+id/uiContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <!-- your UI here -->
    </LinearLayout>   
</RelativeLayout>

In your AsyncTask.onPreExecute() method:

protected void onPreExecute()
{
    progressBar.setVisibility (View.VISIBLE);
    uiContainer.setVisibility (View.INVISIBLE); // optional, up to you if you need to hide your UI
    // Do other things here
}

And in AsyncTask.onPostExecute (Result result)

protected void onPostExecute(Result result)
{
    progressBar.setVisibility (View.GONE);
    uiContainer.setVisibility (View.VISIBLE); // refer to the optional above in onPreExecute
    // Do other things here
}

Again, this is an example, customize/use it as you see fit

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top