Héctor Valido
Héctor Valido

Reputation: 31

Show a loading spinner while a fragment is loading

I have developed a fragment-based app.

I have a menu fragment with buttons,these buttons open a new fragment each one, replacing the last one.

The issue is, that some fragment takes a while in opening cause it does some calls to asynctasks and populates some listviews.

So when I press the button in the menu fragment, it keeps freezed 2 seconds until the new fragment appears replacing the menu fragment.

I would like that a spinner or "loading.." dialog appears in that time.

I have tested this

        private progressDialog progressDialog;
        progressDialog = new ProgressDialog(this);
        progressDialog.setIndeterminate(true);
        progressDialog.setMessage("Loading...");
        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        progressDialog.show();

This code show the dialog but it never shows it when the screen is freezed.

Where I should place that code? in the activity which contains all fragments or in the menu fragment? or maybe in the fragment which is loaded?

I dont get to accomplish this so when in my menu fragment I press the button I do the following code.

         NewAppointmentFragment fragment = new NewAppointmentFragment();
                android.support.v4.app.FragmentTransaction fragmentTransaction =

        getActivity().getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.fragment_container, fragment, 
        "NewAppointmentFragment");
                fragmentTransaction.addToBackStack(null);
                fragmentTransaction.commit();

but it takes 2 seconds until this new fragment is loaded and appears The freezed 2 seconds you can see the menu fragment with the button pressed

Could be cause in the new fragment I call all the asynctasks and operations to populate listviews in OnCreateView ?

How could I resolve this issue?

Thanks in advance

My menu fragment

      @Override
         public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
         View rootView = inflater.inflate(R.layout.fragment_main, container, false);


         nextAppointmentsButton = (Button) 
         rootView.findViewById(R.id.nextAppointmentsButton);
         nuevaCitaButton = (Button) rootView.findViewById(R.id.nuevaCitaButton);
         nearbyPharmaciesButton = (Button) 
         rootView.findViewById(R.id.nearbyPharmaciesButton);
         ourLocationButton = (Button) rootView.findViewById(R.id.ourLocationButton);

         nextAppointmentsButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                UpcomingAppointmentsFragment fragment = new 
         UpcomingAppointmentsFragment();
                android.support.v4.app.FragmentTransaction fragmentTransaction =

          getActivity().getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.fragment_container, fragment);
                fragmentTransaction.addToBackStack(null);
                fragmentTransaction.commit();

            }

         });

         nuevaCitaButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 ((MainActivity)getActivity()).showProgressDialog();
                 NewAppointmentFragment fragment = new NewAppointmentFragment();
                 android.support.v4.app.FragmentTransaction fragmentTransaction =

         getActivity().getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.fragment_container, fragment, 
         "NewAppointmentFragment");
                fragmentTransaction.addToBackStack(null);
                fragmentTransaction.commit();
            }

        });

        nearbyPharmaciesButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                NearbyPharmaciesFragment fragment = new NearbyPharmaciesFragment();
                android.support.v4.app.FragmentTransaction fragmentTransaction =

        getActivity().getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.fragment_container, fragment);
                fragmentTransaction.addToBackStack(null);
                fragmentTransaction.commit();

            }

        });
        ourLocationButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                OurLocationMapFragment fragment = new OurLocationMapFragment();
                android.support.v4.app.FragmentTransaction fragmentTransaction =

        getActivity().getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.fragment_container, fragment);
                fragmentTransaction.addToBackStack(null);
                fragmentTransaction.commit();
            }

        });


        // Inflate the layout for this fragment
        return rootView;
        }

My new Fragment loaded when I press the menu button

      public View onCreateView(LayoutInflater inflater, ViewGroup container,
                     Bundle savedInstanceState) {
       View rootView = inflater.inflate(R.layout.fragment_new_appointment, 
        container, false);

      // **Calls to asynctasks **
      // **Populate operations ListViews**

      return rootView;
      }

Upvotes: 2

Views: 14019

Answers (4)

Syed Zeeshan
Syed Zeeshan

Reputation: 570

You are probably doing long running tasks which blocks the UI thread. First thing you have to do is switch to Kotlin and then,

  1. Create a viewmodel

  2. Add a function in viewmodel which returns a flow

    fun doTask() = flow { val result = withContext(Dispatchers.IO) { // do your task here. // Below is an example code val myResult = 1 + 1 myResult } emit(result) }

  3. In fragment, create a scope like

    showProgress() viewLifeCycleOwner.lifeCycleScope.launch { viewModel.doTask().collectLatest { result -> hideProgress() }

    }

Upvotes: 0

beeb
beeb

Reputation: 1615

If you follow these steps your UI should not freeze:

  1. Load the new fragment
  2. Start Async task
  3. Initialize Progressdialog in constructor of AsyncTask where you want to load the data
  4. Show Progressdialog in onPreExecute() in your AsyncTask with dialog.show()
  5. Dismiss the Progressdialog in onPostExecute() in your AsyncTask with dialog.dismiss()
  6. Update the UI / set the new data to your adapter etc.

Upvotes: 0

Kayo Lima
Kayo Lima

Reputation: 740

I suggest that you put a ProgressBar widget inside your layout:

<ProgressBar
    android:id="@+id/progress_bar"
    style="@style/Base.Widget.AppCompat.ProgressBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:indeterminate="true"
    android:visibility="visible" />

Then in your fragment:

ProgressBar mProgressBar;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
 View view = inflater.inflate(R.layout.fragment, container, false);
 mProgressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
 //other references
 return view;
}

When you finish your http request:

mProgressBar.setVisibility(View.GONE);

Upvotes: 1

Athelon
Athelon

Reputation: 319

private ProgressDialog mProgressDialog;

mProgressDialog = new ProgressDialog(this);

mProgressDialog.setMessage("Working ...");

private void doSomeWorkMethod() {

mProgressDialog.show();

doSomeWork . . .

mProgressDialog.dismiss();

Snackbar.make(v, "Work Complete.", Snackbar.LENGTH_LONG)
  .setAction("Action", null).show();
}

Upvotes: 0

Related Questions