我使用AsyncTask类从php文件下载数据。下载后,我想把这些数据,到不同的TextViews,但我不能使用方法findViewById。
问题是,我是通过单独的类来做到这一点的,而且这一切都在一个片段中。
这是我的代码:
public class RecuperarComentarisFoto extends AsyncTask<String, String, String>{
private Context mContext;
[...]
public RecuperarComentarisFoto(Context context){
this.mContext=context;
}
@Override
protected void onPreExecute() {
[...]
}
@Override
protected String doInBackground(String... arg0) {
params.add(new BasicNameValuePair("pid", "1"));
JSONObject json = jsonParser.makeHttpRequest(url_get_comentaris, "GET", params);
JSONArray productObj;
//HERE I RETRIEVE DATA FROM JSON. ITS WORKING OK.
return null;
}
我的问题在哪里:
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
this.pDialog.dismiss();
TextView comentariEditText = (TextView) findViewById(R.id.commentsMostrar);
}
我试过了:
TextView comentariEditText = (TextView) mContext.findViewById(R.id.commentsMostrar);
但是也不工作。
请注意,我从一个片段调用这个AsyncTask。如您所见,我必须将getActivity()检索到的上下文传递给AsyncTask:
public class MyFragmentA extends Fragment {
Context cont;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View myFragmentView = inflater.inflate(R.layout.fragment_a, container, false);
cont=getActivity();
new RecuperarComentarisFoto(cont).execute();
return myFragmentView;
}
}
我该怎么办?
谢谢。
像这样传递你的膨胀视图给AsyncTask:
public class RecuperarComentarisFoto extends AsyncTask<String, String, String>{
private Context mContext;
private View rootView;
[...]
public RecuperarComentarisFoto(Context context, View rootView){
this.mContext=context;
this.rootView=rootView;
}
@Override
protected void onPreExecute() {
[...]
}
@Override
protected String doInBackground(String... arg0) {
params.add(new BasicNameValuePair("pid", "1"));
JSONObject json = jsonParser.makeHttpRequest(url_get_comentaris, "GET", params);
JSONArray productObj;
//HERE I RETRIEVE DATA FROM JSON. ITS WORKING OK.
return null;
}
@Override
protected void onPostExecute(String result) {
//super.onPostExecute(result); <--GET RID OF THIS (it will screw up on 2.1 devices)
this.pDialog.dismiss();
// use rootview to findViewById
TextView comentariEditText = (TextView) rootView.findViewById(R.id.commentsMostrar);
}
然后像这样调用,
View myFragmentView = inflater.inflate(R.layout.fragment_a, container, false);
cont=getActivity();
new RecuperarComentarisFoto(cont, myFragmentView).execute();
试试这个((Activity)context)
,它适合我…
TextView comentariEditText =
(TextView) ((Activity)context).findViewById(R.id.commentsMostrar);
让AsyncTask独立于Activity
如果
- 你的
AsyncTask
是一个单独的Java类(活动之外)并且仍然想要访问任何Activity
的View元素AsyncTask
。 - 你想重用你的
AsyncTask
与一些其他活动没有AsyncTask
中的任何代码更改
答案是 。使用接口
优势?
接口使事物独立(松散耦合)
您可以遵循以下步骤:
1)创建接口
public interface AsyncTaskListener{
public void giveProgress(int progress);
}
2)在AsyncTask中使用listener
DownloadSongTask extends AsyncTask<String,Integer,Void>{
private AsyncTaskListener listener;
public DownloadSongTask(Context context)
{
listener= (AsyncTaskListener)context; // Typecast
}
@Override
public void doInbackGround(String... params)
{
// Download code
int downloadPerc = // calculate that
publish(downloadPerc);
}
@Override
public void onProgressUpdate(Integer... params)
{
listener.giveProgress(params[0]); // Use it
}
}
3)在Activity和Override方法
中实现接口 public class YourActivity extends AppcompatActivity implements AsyncTaskListener{
private TextView textView;
// Activity code //
new DownloadSongTask(this).execute("Paradise.mp3"); // this is how you start Task
@Override
public void giveProgress(int progress){
textView.setText(progress+"");
}
}
未来你不会意识到你的代码之美,直到你不得不在其他活动中使用你的AsyncTask。
让我们假设在将来你想在一些其他活动中使用这个AsyncTask
来显示一个旋转器的进度。
你将如何使用它?简单!
public class YourActivity extends AppcompatActivity implements AsyncTaskListener{
private Spinner spinner;
// Activity code //
new DownloadSongTask(this).execute("Paradise.mp3"); // this is how you start Task
@Override
public void giveProgress(int progress){
// Your Spinner code
}
}
try as after传递MyFragmentA
context而不是getActivity()
:
cont=this;
new RecuperarComentarisFoto(cont).execute();
并将RecuperarComentarisFoto
更改为
public class RecuperarComentarisFoto extends AsyncTask<String, String, String>{
public Fragment mContext;
[...]
public RecuperarComentarisFoto(Fragment context){
this.mContext=context;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
this.pDialog.dismiss();
TextView comentariEditText =
(TextView)mContext.findViewById(R.id.commentsMostrar);
}
//...your code..
只需添加一个额外的参数到您的AsyncTask与视图myFragmentView,并找到您的textview上。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View myFragmentView = inflater.inflate(R.layout.fragment_a, container, false);
cont=getActivity();
new RecuperarComentarisFoto(cont, myFragmentView).execute();
return myFragmentView;
}
然后使用那个视图。
TextView comentariEditText = (TextView) mView.findViewById(R.id.commentsMostrar);
您可以使您的myFragmentView
全局,这样您就可以从任何地方访问您的视图,甚至从您的片段方法,如onStart()
。
使用RecuperarComentarisFoto(Context context, View rootView)
接受的答案给了我这样的消息:
javaMyFragmentA.java:64: error: constructor RecuperarComentarisFoto in class RecuperarComentarisFoto cannot be applied to given types;
new RecuperarComentarisFoto(cont, myFragmentView).execute();
^
required: no arguments
found: MyFragmentA,View
reason: actual and formal argument lists differ in length
我不知道为什么结果与上面的建议不同。我使用API版本24。
因此,我在AsyncTask
:
initialize()
:public class RecuperarComentarisFoto extends AsyncTask<String, String, String>{
private Context mContext;
private View rootView;
...
public initialize(Context context, View rootView){
this.mContext=context;
this.rootView=rootView;
}
...
}
和调用MyFragmentA类的内部:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
View myFragmentView = inflater.inflate(R.layout.fragment_a, container, false);
cont=getActivity();
RecuperarComentarisFoto rcf = new RecuperarComentarisFoto();
rcf.initialize(cont, myFragmentViewt);
rcf.execute(this);
...
}