Android开发-AsyncTask在片段中的错误实现?
我最近开始尝试在我的Android项目片段中实现异步任务,并立即遇到一个常见错误,即配置更改导致了一个重大问题。我在网上看到的方法并不容易融入我的ViewPager设置中,我用自己的知识来处理配置更改 我的问题是:我的方法有什么危险吗?最大的问题是内存泄漏,但我确保在ondeach()方法上清空每个创建的_视图 执行情况摘要:Android开发-AsyncTask在片段中的错误实现?,android,android-fragments,android-asynctask,fragment,Android,Android Fragments,Android Asynctask,Fragment,我最近开始尝试在我的Android项目片段中实现异步任务,并立即遇到一个常见错误,即配置更改导致了一个重大问题。我在网上看到的方法并不容易融入我的ViewPager设置中,我用自己的知识来处理配置更改 我的问题是:我的方法有什么危险吗?最大的问题是内存泄漏,但我确保在ondeach()方法上清空每个创建的_视图 执行情况摘要: 将片段的setRetainInstance设置为true,这样就不必重新创建它,也不会丢失重要数据 在onCreateView()中,当必须重新创建片段的视图时,始终调
- 将片段的setRetainInstance设置为true,这样就不必重新创建它,也不会丢失重要数据
- 在onCreateView()中,当必须重新创建片段的视图时,始终调用代码部分,应用程序将检查其AsyncTask是否正在运行。如果是这样,则显示一个不确定的进度条,当它完成onPostExecute时,将其可见性更改为GONE
- 在
中,确保已创建的视图设置为null,这样就不会出现与最初使用的活动相关的内存泄漏onDetach()
- 在配置更改前的
onAttach
公共类RosterFragment扩展片段
{
List dataforlotster=new ArrayList();//将保存从解析数据库检索到的花名册对象的列表,
//然后将其传递给RosterCustomArrayaAdapter的构造函数。
检索到的列表\u List=new ArrayList();//将保存从ParseUser查询检索到的值的列表。
View createdView;//将与构建的RosterFragment一起传回的视图
private ProgressBar花名册\u progress;//在异步任务完成花名册下载之前将显示的不确定进度栏。
布尔运行任务;
私人RosterAsyncTask获取花名册;
@凌驾
创建时的公共void(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//跨配置更改保留此片段。
setRetainInstance(真);
get_花名册=new RosterAsyncTask();//创建新的RosterAsyncTask实例。
获取花名册。执行();
正在运行_task=true;
}
@凌驾
CreateView上的公共视图(布局、充气机、视图组容器、捆绑包保存状态)
{
createdView=充气机。充气(R.layout.rosterfragment,container,false);//使用特定布局充气碎片
花名册\进度=(ProgressBar)createdView.findViewById(R.id.LoadingFloster);//在布局中查找进度栏并将其设置为花名册\进度。
if(运行_任务==true)
{
花名册\进度设置可见性(视图可见);
}
其他的
{
填写花名册();
}
返回createdView;
}
@凌驾
公共无效连接()
{
super.onDetach();
createdView=null;
}
公共填补空缺名册()
{
如果(!datafor花名册.isEmpty())
{
//获取膨胀布局中的引用ListView。
ListView_花名册=(ListView)createdView.findViewById(R.id.rostercoachofficers);
//使用DataForFloster列表创建RosterCustomArrayAdapter的实例。
RosterCustomArrayAdapter花名册\ U适配器=新的RosterCustomArrayAdapter(getActivity(),DataFor花名册);
//对花名册适配器进行排序,以便ListView中的元素按名字的字母顺序进行排序。
花名册适配器.sort(新花名册比较程序());
//将适配器连接到ListView以填充其数据。
setAdapter(花名册适配器);
}
}
//AsyncTask负责在后台线程中下载花名册。
私有类RosterAsyncTask扩展异步任务
{
//要在AsyncTask后台线程中执行的操作。结果(下载的花名册数据)将传递给onPostExecute。
@凌驾
受保护列表doInBackground(无效…参数)
{
系统时钟。睡眠(10000);
ParseQuery query=ParseUser.getQuery();//为ParseUsers获取特定的ParseQuery。
尝试
{
已检索_list=query.find();//启动查询。
for(ParseUser current\u user:retrieved\u list)//对于从查询返回的每个ParseUser,使用ParseUser创建一个新的名册成员
//数据,然后将其添加到DataForFloster列表中。
{
名册成员当前成员=新名册成员();
current_member.username=current_user.getUsername();
ParseFile parse_ByteArray=(ParseFile)current_user.get(“profile_picture”);
位图配置文件\u Picture=BitmapFactory.decodeByteArray(parse\u ByteArray.getData(),0,parse\u ByteArray.getData().length);
当前_member.profile_Picture=profile_Picture;
current_member.title=当前_user.getString(“title”);
添加(当前_成员);
}
}
//若查询执行中出现问题,请使用Toast显示错误消息。
捕获(解析异常)
{
Toast.makeText(getActivity(),“Error,”+e.getMessage(),Toast.LENGTH_LONG.show();
}
返回花名册数据;
}
//doinBackground方法完成后在主UI线程中运行的代码。
@凌驾
受保护的void onPostExecute(列出DataForFloster)
{
正在运行_task=false;
填写花名册();
花名册_progress.setVisibility(View.GONE);
}
}
}
我能看到的两件主要事情都与你的活动有关。doInBackground()中的toast需要从主线程调用,因此我确信这将失败。您传递给适配器的活动也与片段分开,因此每当您有一个配置更改将被销毁且不再有效时
为了帮助防止任何强制关闭,您可能希望用发送给logcat的消息替换toast,并在执行之前验证活动和进度是否为空
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);
}
}
}
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;
private boolean successful_query;
private String error_message;
@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.
fill_roster();
return createdView;
}
@Override
public void onDetach()
{
super.onDetach();
createdView = null;
}
public void fill_roster()
{
if(running_task == true)
{
roster_progress.setVisibility(View.VISIBLE);
}
else
{
roster_progress.setVisibility(View.GONE);
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);
}
else
{
if(successful_query == false)
{
Toast.makeText(getActivity(), error_message, Toast.LENGTH_LONG).show();
}
}
}
}
//AsyncTask responsible for downloading roster in background thread.
private class RosterAsyncTask extends AsyncTask<Void, Void , Void>
{
//The operations to perform in the AsyncTask background thread. The results(the roster data downloaded) will be passed to onPostExecute.
@Override
protected Void doInBackground(Void... params)
{
dataforroster.clear();
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);
}
successful_query = true;
}
//If problem occurred in query execution, use Toast to display error message.
catch (ParseException e)
{
successful_query = false;
error_message = "Error, " + e.getMessage();
}
return null;
}
//Code to run in main UI thread once the doinBackground method is finished.
@Override
protected void onPostExecute(Void ignore)
{
running_task = false;
if(getActivity()!=null)
{
fill_roster();
}
}
}
}