Недавно я начал пытаться внедрить AsyncTasks в фрагменты моего Android-проекта и сразу же столкнулся с общей ошибкой изменения конфигурации, вызвавшей серьезную проблему. Методы, которые я видел в Интернете, нелегко включали в настройку ViewPager, которую я использовал, и я использовал свои знания для самостоятельной обработки изменений конфигурации.Разработка Android - Неверная реализация AsyncTask в фрагменте?
Мой вопрос: есть ли что-нибудь опасное для моего подхода? Наибольшее беспокойство вызывает утечка памяти, но я позаботился об отказе каждого созданного_View в методе onDetach().
Резюме реализации:
setRetainInstance истина для фрагмента, чтобы он не должен быть воссоздан и важные данные не теряются.
В onCreateView() раздел кода, всегда вызываемый при восстановлении вида фрагмента, приложение проверяет, работает ли его AsyncTask. Если это так, отобразите IndeterminateProgressBar, и когда он завершит onPostExecute, измените видимость его на GONE.
В
onDetach()
, убедитесь, что created_view View установлен в нуль, так что нет утечки памяти, связанной с деятельностью, которая первоначально используются- в
onAttach
до изменения конфигурации.
Код
public class RosterFragment extends Fragment
{
List<RosterMember> dataforroster = new ArrayList<RosterMember>(); //List that will hold the Roster objects retrieved from Parse database,
//and later passed in to constructor for the RosterCustomArrayAdapter.
List<ParseUser> retrieved_list = new ArrayList<ParseUser>(); //List that will hold values retrieved from ParseUser Query.
View createdView; //View that will be passed back with built RosterFragment
private ProgressBar roster_progress; //The indeterminate ProgressBar that will be displayed until the AsyncTask is finished downloading the roster.
boolean running_task;
private RosterAsyncTask get_roster;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Retain this fragment across configuration changes.
setRetainInstance(true);
get_roster = new RosterAsyncTask(); //Create new RosterAsyncTask instance.
get_roster.execute();
running_task = true;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{
createdView = inflater.inflate(R.layout.rosterfragment, container, false); //Inflate the fragment using the specific layout
roster_progress = (ProgressBar) createdView.findViewById(R.id.loadingroster); //Find the ProgressBar in layout and set it to roster_progress.
if(running_task == true)
{
roster_progress.setVisibility(View.VISIBLE);
}
else
{
fill_roster();
}
return createdView;
}
@Override
public void onDetach()
{
super.onDetach();
createdView = null;
}
public void fill_roster()
{
if(!dataforroster.isEmpty())
{
//Get reference ListView in the inflated layout.
ListView the_Roster = (ListView) createdView.findViewById(R.id.rostercoachofficers);
//Create an instance of the RosterCustomArrayAdapter using the dataforroster List.
RosterCustomArrayAdapter roster_Adapter = new RosterCustomArrayAdapter(getActivity(), dataforroster);
//Sort the roster_Adapter so elements in ListView will be sorted alphabetically by first name.
roster_Adapter.sort(new RosterComparator());
//Attach adapter to the ListView to populate its data.
the_Roster.setAdapter(roster_Adapter);
}
}
//AsyncTask responsible for downloading roster in background thread.
private class RosterAsyncTask extends AsyncTask<Void, Void , List<RosterMember>>
{
//The operations to perform in the AsyncTask background thread. The results(the roster data downloaded) will be passed to onPostExecute.
@Override
protected List<RosterMember> doInBackground(Void... params)
{
SystemClock.sleep(10000);
ParseQuery<ParseUser> query = ParseUser.getQuery(); //Get specific ParseQuery for ParseUsers.
try
{
retrieved_list = query.find(); //Initiate query.
for(ParseUser current_user: retrieved_list) //For every ParseUser returned from query, create a new RosterMember using the ParseUser
//data and then add it to the dataforroster List.
{
RosterMember current_member = new RosterMember();
current_member.username = current_user.getUsername();
ParseFile parse_ByteArray = (ParseFile)current_user.get("profile_picture");
Bitmap profile_Picture = BitmapFactory.decodeByteArray(parse_ByteArray.getData(), 0, parse_ByteArray.getData().length);
current_member.profile_Picture = profile_Picture;
current_member.title = current_user.getString("title");
dataforroster.add(current_member);
}
}
//If problem occurred in query execution, use Toast to display error message.
catch (ParseException e)
{
Toast.makeText(getActivity(), "Error, " + e.getMessage(), Toast.LENGTH_LONG).show();
}
return dataforroster;
}
//Code to run in main UI thread once the doinBackground method is finished.
@Override
protected void onPostExecute(List<RosterMember> dataforroster)
{
running_task = false;
fill_roster();
roster_progress.setVisibility(View.GONE);
}
}
}
В чем проблема, с которой вы сталкиваетесь? – Raghunandan
Спасибо Рагхунандану за быстрый ответ. На самом деле это не проблема, приложение работает с изменением конфигурации (ориентация экрана), которую я пробовал во время работы AsyncTask. Но я хочу, чтобы контур, который я разработал, эффективен и не вызывал утечки памяти. Эта утечка памяти вызывает беспокойство, потому что я хочу проверить, что старые действия не исключаются из сбора мусора, потому что все еще есть ссылка на них. – blkhatpersian