从 AsyncTask 更新视图
Posted
技术标签:
【中文标题】从 AsyncTask 更新视图【英文标题】:Update view from AsyncTask 【发布时间】:2019-05-23 01:28:04 【问题描述】:我想从android中的mysql数据库中检索数据并在textview中显示
显示错误
E/AndroidRuntime: 致命异常: main 进程:com.example.learnersarena.practicemysql,PID:23452 java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“void android.widget.TextView.setText(java.lang.CharSequence)” 在 com.example.learnersarena.practicemysql.BackgroundAsyncTask.onPostExecute(BackgroundAsyncTask.java:110) 在 com.example.learnersarena.practicemysql.BackgroundAsyncTask.onPostExecute(BackgroundAsyncTask.java:26) 在 android.os.AsyncTask.finish(AsyncTask.java:632) 在 android.os.AsyncTask.access$600(AsyncTask.java:177) 在 android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:135) 在 android.app.ActivityThread.main(ActivityThread.java:5349) 在 java.lang.reflect.Method.invoke(本机方法) 在 java.lang.reflect.Method.invoke(Method.java:372) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
这是后台异步任务代码
public class BackgroundAsyncTask extends AsyncTask<String, Void, String>
Context ctx;
TextView tv;
BackgroundAsyncTask(Context ctx)
this.ctx = ctx;
protected void onPreExecute()
super.onPreExecute();
@Override
protected String doInBackground(String... params)
String insert_url="http://192.168.10.3:81/android_exam_practice/insert.php";
String select_url="http://192.168.10.3:81/android_exam_practice/select.php";
String method=params[0];
if(method.equals("insert"))
String name=params[1];
String email=params[2];
try
URL url=new URL(insert_url);
HttpURLConnection httpURLConnection=(HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoOutput(true);
OutputStream outputStream=httpURLConnection.getOutputStream();
BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(outputStream,"UTF-8"));
String data= URLEncoder.encode("name","UTF-8")+"="+URLEncoder.encode(name,"UTF-8")+"&"+
URLEncoder.encode("email","UTF-8")+"="+URLEncoder.encode(email,"UTF-8");
bufferedWriter.write(data);
bufferedWriter.flush();
outputStream.close();
InputStream inputStream=httpURLConnection.getInputStream();
inputStream.close();
return "data inserted ";
catch (MalformedURLException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
else if(method.equals("select"))
// String Name=params[1];
// String Email=params[2];
try
URL url=new URL(select_url);
HttpURLConnection httpURLConnection=(HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("post");
httpURLConnection.setDoInput(true);
httpURLConnection.setDoOutput(true);
//OutputStream outputStream=httpURLConnection.getOutputStream();
//BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(outputStream,"UTF-8"));
//String data =URLEncoder.encode("");
InputStream inputStream=httpURLConnection.getInputStream();
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream,"iso-8859-1"));
String response ="";
String line ="";
while((line=bufferedReader.readLine())!=null)
response+=line;
bufferedReader.close();
inputStream.close();
httpURLConnection.disconnect();
catch (MalformedURLException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
return null;
@Override
protected void onProgressUpdate(Void... values)
super.onProgressUpdate(values);
@Override
protected void onPostExecute(String aVoid)
super.onPostExecute(aVoid);
// Toast.makeText(ctx, aVoid, Toast.LENGTH_SHORT).show();
tv.setText(aVoid);
【问题讨论】:
你永远不会初始化你的 TextView 所以你的 tv 变量总是 null ,当你想在那个 TextView 上设置文本时,你会得到这个,在你的代码中的某个地方启动它 那么我该如何解决这个问题? 您必须有一个xml布局文件并在该文件中定义您的TextView,并启动您的TextView在布局文件中具有的textview throw id,或者您可以创建动态TextView,并将其绑定到您的以编程方式进行用户界面 我有 3 个 java 类 2 个有 xml 文件,一个不是 BackgroundAsyncTask 是一个 java 文件没有 xml 文件 【参考方案1】:您的解决方案就在这里。
在您的onPostExecute()
方法中初始化textview
@Override
protected void onPostExecute(String aVoid)
super.onPostExecute(aVoid);
// Toast.makeText(ctx, aVoid, Toast.LENGTH_SHORT).show();
tv = findViewById(R.id.textView);
tv.setText(aVoid);
【讨论】:
【参考方案2】:BackgroundAsyncTask 在您的应用程序中是一个线程而不是 UI 线程,因此如果您需要更新任何视图,您可以创建一个 public 和 static Activity/Fragment 中的方法并使用 runOnUiThread() 方法调用此方法:
runOnUiThread(new Runnable()
public void run()
// call your method here.
);
或
利用 Handler 的 check this to know more about Handler's
【讨论】:
【参考方案3】:将BackgroundAsyncTask
的构造函数从:
BackgroundAsyncTask(Context ctx)
this.ctx = ctx;
到
BackgroundAsyncTask(Context ctx, TextView tv)
this.ctx = ctx;
this.tv = tv;
因此,当您在活动中初始化 BackgroundAsyncTask
时,而不是:
new BackgroundAsyncTask(this)
写
new BackgroundAsyncTask(this, tv)
其中tv
是您要更新的活动的TextView
。
【讨论】:
以上是关于从 AsyncTask 更新视图的主要内容,如果未能解决你的问题,请参考以下文章
从两个不同的 AsyncTask 更新一个 ListView