我为Android制作了一个最初针对较低版本(2.3)的应用程序。在我的概念验证工作之后,我试图让它在Android 4上运行。那时我得到了NetworkOnMainThread异常。
在做了一些研究后,我很快找到了AsyncTask,听起来很棒。问题是,我很难绕过它。例如,这是我的原始代码:
public void Refresh(Context c)
{
SummaryModel model = MobileController.FetchSummary(c);
TextView txtCurrentWeight = (TextView)findViewById(R.id.txtCurrentWeight);
TextView txtWeightChange = (TextView)findViewById(R.id.txtWeightChange);
TextView txtAvgPerWeek = (TextView)findViewById(R.id.txtAvgPerWeek);
if(model.ErrorMessage == "")
{
txtCurrentWeight.setText(model.CurrentWeight);
txtWeightChange.setText(model.WeightChange);
txtAvgPerWeek.setText(model.Average);
}
else
{
Toast.makeText(c, model.ErrorMessage, Toast.LENGTH_LONG).show();
txtCurrentWeight.setText("");
txtWeightChange.setText("");
txtAvgPerWeek.setText("");
}
}
我创建了一个像这样的AsychTask:
public class WebMethodTask extends AsyncTask<Object, Integer, Object> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
SummaryModel model = (SummaryModel)result;
// Can't seem to access UI items here??
}
@Override
protected Object doInBackground(Object... params) {
Context c = (Context)params[0];
return MobileController.FetchSummary(c);
}
}
如何从onPostExecute方法访问UI项目?或者,我对如何使用AsyncTask有错误的想法吗?
谢谢!
答案 0 :(得分:2)
您应该可以在您放置评论的地方访问(在postExecute
方法中)
此外,我建议为AsyncTask使用更专业的类,以便您的代码看起来更好:
public class WebMethodTask extends AsyncTask<Object, Integer, SummaryModel> {
private Activity source;
public WebMethodTask(Activity activity) {
this.source=activity;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(SummaryModel model) {
super.onPostExecute(model );
TextView txtCurrentWeight = (TextView)source.findViewById(R.id.txtCurrentWeight);
TextView txtWeightChange = (TextView)source.findViewById(R.id.txtWeightChange);
TextView txtAvgPerWeek = (TextView)source.findViewById(R.id.txtAvgPerWeek);
if(model.ErrorMessage.length()==0)
{
txtCurrentWeight.setText(model.CurrentWeight);
txtWeightChange.setText(model.WeightChange);
txtAvgPerWeek.setText(model.Average);
}
else
{
Toast.makeText(c, model.ErrorMessage, Toast.LENGTH_LONG).show();
txtCurrentWeight.setText("");
txtWeightChange.setText("");
txtAvgPerWeek.setText("");
}
}
@Override
protected SummaryModel doInBackground(Context ... params) {
Context c = params[0];
return MobileController.FetchSummary(c);
}
}
修改:添加了对您的活动的引用,以考虑您的上次评论。
但是,如果你的acynctask可能很长,那么保持对某个活动的引用可能不是一个好主意。
创建一个接受一些displayModel(CummaryModel)
方法的监听器类是一个更好的设计,如果活动没有暂停/停止,它的责任是调用setText方法......
答案 1 :(得分:0)
使用WebMethodTask#onPostExecute方法中的加载模型数据填充ui项目。
答案 2 :(得分:0)
您需要对UI控件的引用。将对UI控件的引用传递给ASyncTask时,您将产生问题。 假设以下情形:
结论是ASyncTask不应该用于与网络活动相关的后台任务。
幸运的是有一个解决方案:RoboSpice。 RoboSpice使用另一种方法。请查看https://github.com/octo-online/robospice/wiki/Understand-the-basics-of-RoboSpice-in-30-seconds以获得更好的解释。 更多信息:https://github.com/octo-online/robospice
答案 3 :(得分:0)
在刷新方法中创建一个内部类
enter code herepublic void Refresh(Context c)
{ SummaryModel model = MobileController.FetchSummary(c);
TextView txtCurrentWeight = (TextView)findViewById(R.id.txtCurrentWeight);
TextView txtWeightChange = (TextView)findViewById(R.id.txtWeightChange);
TextView txtAvgPerWeek = (TextView)findViewById(R.id.txtAvgPerWeek);
if(model.ErrorMessage == "")
{
txtCurrentWeight.setText(model.CurrentWeight);
txtWeightChange.setText(model.WeightChange);
txtAvgPerWeek.setText(model.Average);
}
else
{
Toast.makeText(c, model.ErrorMessage, Toast.LENGTH_LONG).show();
txtCurrentWeight.setText("");
txtWeightChange.setText("");
txtAvgPerWeek.setText("");
}
class WebMethodTask extends AsyncTask<Object, Integer, Object> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
SummaryModel model = (SummaryModel)result;
// Can't seem to access UI items here??
}
@Override
protected Object doInBackground(Object... params) {
Context c = (Context)params[0];
return MobileController.FetchSummary(c);
}
}
}