我最近开始尝试在我的 Android 项目的 Fragments 中实现AsyncTasks,并立即遇到了配置更改导致重大问题的常见错误。我在网上看到的方法并没有轻易地融入到我拥有的 ViewPager 设置中,我利用我的知识将自己处理配置更改结合起来。
我的问题是:我的方法有什么危险吗?最大的担忧是内存泄漏,但我确保在 onDetach() 方法上将每个 created_View 都清空。
实施总结:
将 Fragment 的 setRetainInstance 设置为 true,因此不必重新创建它,并且不会丢失重要数据。
在 onCreateView() 中,当必须重新创建 Fragment 的视图时始终调用的代码部分,应用程序将检查其 AsyncTask 是否正在运行。如果是这样,显示一个 IndeterminateProgressBar,当它完成 onPostExecute 时,将它的可见性更改为 GONE。
在
onDetach()
中,确保 created_view 视图设置为 null,这样就没有与最初使用的 Activity 相关的内存泄漏- 在
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);
}
}
}