При использовании AsyncTask следует учитывать следующий момент. Более оптимальным способом является работа AsyncTask с фрагментом, нежели непосредственно с activity. Например, если мы возьмем проект из прошлой темы, запустим приложение и изменим ориентацию мобильного устройства, то произойдет пересоздание activity. В случае изменения орентации устройства поток AsyncTask будет продолжать обращаться к старой activity, вместо новой. Поэтому в этом случае лучше использовать фрагменты.
Итак, возьмем проект из прошлой темы и добавим в него новый фрагмент, который назовем ProgressFragment.
Определим для него новый файл разметки интерфейса fragment_progress.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_progress" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="16dp" android:orientation="vertical"> <Button android:id="@+id/progressBtn" android:text="Запуск" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/statusView" android:text="Статус" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ProgressBar android:id="@+id/indicator" style="@android:style/Widget.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="100" android:progress="0" /> </LinearLayout>
Сам класс фрагмента ProgressFragment изменим следующим образом:
package com.example.eugene.asyncapp; import android.widget.Button; import android.os.AsyncTask; import android.os.Bundle; import android.app.Fragment; import android.os.SystemClock; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import android.view.View.OnClickListener; public class ProgressFragment extends Fragment { int[] integers=null; ProgressBar indicatorBar; TextView statusView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_progress, container, false); integers = new int[100]; for(int i=0;i<100;i++) { integers[i] = i + 1; } indicatorBar = (ProgressBar) view.findViewById(R.id.indicator); statusView = (TextView) view.findViewById(R.id.statusView); Button btnFetch = (Button)view.findViewById(R.id.progressBtn); btnFetch.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new ProgressTask().execute(); } }); return view; } class ProgressTask extends AsyncTask<Void, Integer, Void> { @Override protected Void doInBackground(Void... unused) { for (int i = 0; i<integers.length;i++) { publishProgress(i); SystemClock.sleep(400); } return null; } @Override protected void onProgressUpdate(Integer... items) { indicatorBar.setProgress(items[0]+1); statusView.setText("Статус: " + String.valueOf(items[0]+1)); } @Override protected void onPostExecute(Void unused) { Toast.makeText(getActivity(), "Задача завершена", Toast.LENGTH_SHORT) .show(); } } }
Здесь определены все те действия, которые были рассмотрены в прошлой теме и которые ранее находились в классе MainActivity. Особо стоит отметить вызов setRetainInstance(true) в методе onCreate(), который позволяет сохранять состояние фрагмента вне зависимости от изменения ориентации.
Теперь свяжем фрагмент с activity. Для этого определим в файле activity_main.xml следующий код:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/progressFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.example.eugene.asyncapp.ProgressFragment"/> </LinearLayout>
А сам класс MainActivity сократим:
package com.example.eugene.asyncapp; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
Теперь если мы запустим приложение, то вне зависимости от смены ориентации моильного устройства фоновая задача будет продолжать свою работу: