从 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 线程,因此如果您需要更新任何视图,您可以创建一个 publicstatic 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

Asynctask 内部类不更新 UI 文本视图

如何在 AsyncTask 类方法中更新列表的文本视图?

从 AsyncTask 更新 setListAdapter

重新创建活动时如何从 AsyncTask 更新 TextView

从 AsyncTask 滞后 UI 更新 ProgressBar