Question

I have a fragment that has a list, and for this list I am wanting a loading icon to appear while the list is loading, and the list to appear afterwards. Here is my list fragment layout that is inflated by calling View rootView = inflater.inflate(R.layout.main_list_card, container, false); in the onCreateView() of the fragment.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity$DummySectionFragment" 
    android:layout_gravity="center">

    <ListView
        android:id="@+id/mainList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@android:color/transparent"
        android:dividerHeight="6dp"
        android:listSelector="@android:color/transparent"
        android:visibility="invisible"/>

    <ProgressBar
        android:id="@+id/loadingIcon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"/>

</FrameLayout>

The idea is that I am calling list.setVisibility(View.INVISIBLE); and bar.setVisibility(View.VISIBLE); while the list is loading, and the opposite once it is loaded. My asynctask is called in the following way (which is called in onResume() of the fragment):

InstalledAppsLoader loader = new InstalledAppsLoader(bar, list);
loader.execute();
try {
    apps = loader.get();
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (ExecutionException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

The problem is once this is called, the UI Thread freezes completely and doesn't even change views yet, then once it is loaded I see a flicker of the Loading Icon and then the list is show and the loading icon dissappears. I am not sure if onCreateView in my fragment is called afterwards or something, but I am trying to let it be called right when the fragment is created that way it shows the list loading. The InstalledAppsLoader class looks like this:

public class InstalledAppsLoader extends AsyncTask<Void, Void, List<App>>{

    private ProgressBar bar;
    private ListView list;

    public InstalledAppsLoader(ProgressBar bar, ListView list)
    {
        this.bar = bar;
        this.list = list;
    }

    @Override
    protected void onPreExecute() {
        bar.setVisibility(View.VISIBLE);
        list.setVisibility(View.INVISIBLE);
        super.onPreExecute();
    }

    @Override
    protected List<App> doInBackground(Void... params) {
        return MainFragment.getInstalledApps();
    }

    @Override
    protected void onPostExecute(List<App> result) {
        bar.setVisibility(View.INVISIBLE);
        list.setVisibility(View.VISIBLE);
        super.onPostExecute(result);
    }


}

I have been stuck on this for a while now since concurrent programming is a relatively new idea to me, so any help would be much appreciated!

No correct solution

OTHER TIPS

Because of this,

try {
    apps = loader.get();
}

As .get() method of AsyncTask is UI thread blocking method. It will not run your AsyncTask Asynchronously.

Also you are calling AsyncTask two times.

loader.execute(); // 1 
try {
    apps = loader.get(); // 2 time
}

remove apps = loader.get(); from UI thread and use apps member in onPostExecute() of your AsyncTask.

Edit:

@Override
protected void onPostExecute(List<App> result) {
    apps = result; // Use apps here
    bar.setVisibility(View.INVISIBLE);
    list.setVisibility(View.VISIBLE);
    super.onPostExecute(result);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top