📜 ⬆️ ⬇️

Work with progress dialogs

Beginners to work with android have questions about creating progress dialogues. My note may help them.

There are several ways to create and launch a dialog, but one thing unites them all: all changes to the visible part of the user interface after creating an Activity must occur in a special thread. Many people forget about it and then wonder why there is no visible change. The simplest option is to call the following construct:

.runOnUiThread(new Runnable() { @Override public void run() { //    } }); 

')
or for View:

 .post(new Runnable() { @Override public void run() { //    } }); 


Your change commands are queued and at some point called Activity. There is an advantage, although at first glance it is not obvious. The program stops to slow down every time the interface changes, all redrawing runs as if it were background, the program does not freeze when performing some computational tasks associated simultaneously with the calculations / loading and displaying the progress of the process. On the other hand, this complicates the code a bit.

Some ready-made functions are already running in this thread. These functions include calls to the dialogues.
Do not use dialog creation directly. For this there is a special mechanism:

1. Assign your dialogue number to each dialog, for example private static final int DIALOG_KEY = 1 .
2. Create dialogs and assign their properties in the rewritable onCreateDialog (int id) method.
3. Call the dialog on the screen using showDialog (DIALOG_KEY) by its number.
4. Delete the unwanted dialog with dismissDialog (DIALOG_KEY) .

Option 1. Call the dialogue in the Activity and stop the dialogue using the handler.



In the above example, the usual ListView is called and an adapter is assigned to it. When you select a list item, the download dialog appears and after the download is completed, the dialogue is deleted. Loading is performed in a separate stream so that your activity does not freeze during the execution of the download! After the download is complete, the handler interceptor is called in order to respond and remove the download dialog that has become unnecessary.

 public class AlphabetView extends Activity { private static final int DIALOG_LOAD_KEY = 1; private Activity context; private Alphabet alphabet; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.alphabet); context = this; alphabet = Main.getAlphabet(); ListView lv = (ListView) findViewById(R.id.ListViewMain); lv.setAdapter(new ArrayAdapter<String>(this, R.layout.item, alphabet.getNames())); //       lv.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final int i = position; showDialog(DIALOG_LOAD_KEY); //   //        new Thread(new Runnable() { public void run() { Main.loadData(i); //     handler.sendEmptyMessage(0); //      } }).start(); } }); } //           Activity private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { dismissDialog(DIALOG_LOAD_KEY); //   Intent intent = new Intent(context, AuthorsView.class); startActivity(intent); } }; @Override //      protected Dialog onCreateDialog(int id) { switch (id) { case DIALOG_LOAD_KEY: { ProgressDialog dialog = new ProgressDialog(this); dialog.setMessage(",  ..."); dialog.setCancelable(true); return dialog; } } return super.onCreateDialog(id); } } 


Option 2. Call the dialogue in the Activity and stop the dialogue without a handler.



In this embodiment, we do not use a handler. Instead, after creating the dialog, we launch the download in a separate thread, and after the download is finished, we delete the dialog using the above-described runOnUiThread .

 public class AlphabetView extends Activity { private static final int DIALOG_LOAD_KEY = 1; private Activity context; private Alphabet alphabet; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.alphabet); context = this; alphabet = Main.getAlphabet(); ListView lv = (ListView) findViewById(R.id.ListViewMain); lv.setAdapter(new ArrayAdapter<String>(this, R.layout.item, alphabet.getNames())); //       lv.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final int i = position; showDialog(DIALOG_LOAD_KEY); //   } }); } @Override //      protected Dialog onCreateDialog(int id) { switch (id) { case DIALOG_LOAD_KEY: { final ProgressDialog dialog = new ProgressDialog(this); dialog.setMessage(",  ..."); dialog.setCancelable(true); new Thread(new Runnable() { @Override public void run() { Main.loadData(); //     //     runOnUiThread(new Runnable() { @Override public void run() { dismissDialog(DIALOG_LOAD_DATA); } }); } }).start(); return progressDialog; } } return super.onCreateDialog(id); } } 


Combinations of these two options are also possible. For example, in the first variant it is possible instead of hadler to also use the code given in the second variant:

  Main.loadData(); //     //     runOnUiThread(new Runnable() { @Override public void run() { dismissDialog(DIALOG_LOAD_DATA); } }); 


Option 3. Call the dialogue in the Activity using AsyncTask.



Sometimes it is more convenient to use the async task AsyncTask. This is described in detail at developer.android.com/resources/articles/painless-threading.html .

For example, you click to call a new asynchronous task to load your file:

 public void onClick(View v) { new DownloadImageTask().execute("http://example.com/image.png"); } 


DownloadImageTask extends the AsyncTask class in which there are all the methods for the normal display of the dialogue. To initialize the dialog, use the onCreateDialog function shown in Example 1.

 private class DownloadImageTask extends AsyncTask<string, void,="" bitmap=""> { protected Bitmap doInBackground(String... urls) { return loadImageFromNetwork(urls[0]); //    } protected void onPreExecute() { showDialog(DIALOG_LOAD_KEY); //   } protected void onProgressUpdate() { //       . } protected void onPostExecute(Bitmap result) { dismissDialog(DIALOG_LOAD_DATA); //   } } 


If someone offers more interesting options, I will be glad.

Source: https://habr.com/ru/post/111846/


All Articles