При использовании 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);
}
}
Теперь если мы запустим приложение, то вне зависимости от смены ориентации моильного устройства фоновая задача будет продолжать свою работу: