【发布时间】:2014-03-10 11:58:45
【问题描述】:
我最近开始尝试在我的 Android 项目的 Fragments 中实现 AsyncTasks,并立即遇到了配置更改导致重大问题的常见错误。我在网上看到的方法并不容易融入我的 ViewPager 设置中,我利用我的知识将自己处理配置更改。
我的问题是:我的方法有什么危险吗?最大的担忧是内存泄漏,但我确保在 onDetach() 方法上将每个 created_View 都清空。
实施总结:
将 Fragment 设置为 true,这样就不必重新创建它,也不会丢失重要数据。
在 onCreateView() 中,当必须重新创建 Fragment 的视图时始终调用的代码部分,应用程序将检查其 AsyncTask 是否正在运行。如果是这样,则显示一个 IndeterminateProgressBar,并在它完成 onPostExecute 后,将其可见性更改为 GONE。
在
onDetach()中,确保created_view 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);
}
}
}
【问题讨论】:
-
您面临的问题是什么?
-
感谢 Raghunandan 的快速回复。这不是一个真正的问题,应用程序已经与我在 AsyncTask 运行时尝试过的配置更改(屏幕方向)一起工作。但我想确保我设计的大纲是高效的,并且不会导致内存泄漏。这个内存泄漏是一个问题,因为我想验证旧的活动没有被排除在垃圾收集之外,因为仍然有对它们的引用。
标签: android android-fragments android-asynctask fragment