java - 使用 Asynctasks 将文本设置为多个 TextField 会导致应用程序崩溃

标签 java android android-asynctask

我想要实现的目标如下: 在我看来,我有 4 个 TextView,它们应该显示所连接数据库中的项目数量。这是使用简单的 php 脚本完成的。

我遇到的问题是我从数据库中获取了所有正确的值,但是当我尝试将这些值设置到我的 TextView 时,应用程序崩溃了。

我试图看看使用许多 Asynctasks 是否会出现问题,但是当我决定注释掉 SetTextForTextView() 函数中的唯一一行时,这一切都像魅力一样工作预期值被打印到我的日志中。话虽这么说,我不认为同时使用多个异步任务是这里的问题,但我真的不知道是什么。

可能值得一提的是,当我像这样注释掉以下内容时,应用程序不会崩溃...

        shoesAmount = (TextView) findViewById(R.id.menuTvShoesAmount);
        DatabaseTask taskA = new DatabaseTask(shoesAmount);
        taskA.execute("getAmount", "shoes");

//        tshirtsAmounts = (TextView) findViewById(R.id.menuTvTshirtsAmount);
//        DatabaseTask taskB = new DatabaseTask(tshirtsAmounts);
//        taskB.execute("getAmount", "tshirts");
//
//        jeansAmount = (TextView) findViewById(R.id.menuTvJeansAmount);
//        DatabaseTask taskC = new DatabaseTask(jeansAmount);
//        taskC.execute("getAmount", "jeans");
//
//        blousesAmount = (TextView) findViewById(R.id.menuTvBlousesAmount);
//        DatabaseTask taskD = new DatabaseTask(blousesAmount);
//        taskD.execute("getAmount", "blouses");

但是,如果再使用任何其他组合(例如像这样的组合),应用程序就会再次崩溃......

//        shoesAmount = (TextView) findViewById(R.id.menuTvShoesAmount);
//        DatabaseTask taskA = new DatabaseTask(shoesAmount);
//        taskA.execute("getAmount", "shoes");
//
        tshirtsAmounts = (TextView) findViewById(R.id.menuTvTshirtsAmount);
        DatabaseTask taskB = new DatabaseTask(tshirtsAmounts);
        taskB.execute("getAmount", "tshirts");
//
//        jeansAmount = (TextView) findViewById(R.id.menuTvJeansAmount);
//        DatabaseTask taskC = new DatabaseTask(jeansAmount);
//        taskC.execute("getAmount", "jeans");
//
//        blousesAmount = (TextView) findViewById(R.id.menuTvBlousesAmount);
//        DatabaseTask taskD = new DatabaseTask(blousesAmount);
//        taskD.execute("getAmount", "blouses");

有人可以指出我可能出错的方向吗?

谢谢! (这是完整的代码)

package ishopper.theindiestudio.com.appname;

import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;

public class Menu extends AppCompatActivity {

    private ImageButton btnHelp, btnAccount, newest1, newest2, newest3;
    private TextView shoesAmount, tshirtsAmounts, jeansAmount, blousesAmount;
    private Button browseShoes, browseTshirts, browseJeans, browseBlouses;

    private Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_menu);

        context = this;

        btnHelp = (ImageButton) findViewById(R.id.menuBtnHelp);
        btnAccount = (ImageButton) findViewById(R.id.menuBtnAccount);

        btnAccount.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onAccountOptions();
            }
        });
        btnHelp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onHelp();
            }
        });

        newest1 = (ImageButton) findViewById(R.id.menuIbNewest1);
        newest2 = (ImageButton) findViewById(R.id.menuIbNewest2);
        newest3 = (ImageButton) findViewById(R.id.menuIbNewest3);
        //set newest items

        shoesAmount = (TextView) findViewById(R.id.menuTvShoesAmount);
        DatabaseTask taskA = new DatabaseTask(shoesAmount);
        taskA.execute("getAmount", "shoes");

        tshirtsAmounts = (TextView) findViewById(R.id.menuTvTshirtsAmount);
        DatabaseTask taskB = new DatabaseTask(tshirtsAmounts);
        taskB.execute("getAmount", "tshirts");

        jeansAmount = (TextView) findViewById(R.id.menuTvJeansAmount);
        DatabaseTask taskC = new DatabaseTask(jeansAmount);
        taskC.execute("getAmount", "jeans");

        blousesAmount = (TextView) findViewById(R.id.menuTvBlousesAmount);
        DatabaseTask taskD = new DatabaseTask(blousesAmount);
        taskD.execute("getAmount", "blouses");

    }

    public void SetTextForTextView(TextView textview, String result){
        textview.setText(result);
    }

    public void onAccountOptions () {
        Intent i = new Intent(this, AccountDetailsActivity.class);
        startActivity(i);
    }

    public void onHelp () {

    }

    public void onBackPressed() {
        //disabled back button
    }

    private class DatabaseTask extends AsyncTask<String, Void, String> {

        private String taskType;
        private String productType;
        private TextView textView;
        private ImageButton imageButton;

        DatabaseTask (TextView mTextView){textView = mTextView;}

        @Override
        protected String doInBackground(String... params) {

            String task = params[0];
            if (task.equals("getAmount")) {
                Log.e("doInBg", "getAmount");

                String login_url = "http://url.eu/directory/script.php";
                String tProductType = params[1];
                try {
                    URL url = new URL(login_url);
                    HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                    httpURLConnection.setRequestMethod("POST");
                    httpURLConnection.setDoOutput(true);
                    httpURLConnection.setDoInput(true);
                    OutputStream outputStream = httpURLConnection.getOutputStream();
                    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
                    String postData = URLEncoder.encode("producttable", "UTF-8") + "=" + URLEncoder.encode(tProductType, "UTF-8");
                    bufferedWriter.write(postData);
                    bufferedWriter.flush();
                    bufferedWriter.close();
                    outputStream.close();
                    InputStream inputStream = httpURLConnection.getInputStream();
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "iso-8859-1"));
                    String result = "";
                    String line = "";
                    while ((line = bufferedReader.readLine()) != null) {
                        result += line;
                        Log.e("doInBgResult", result.toString());
                    }
                    bufferedReader.close();
                    inputStream.close();
                    httpURLConnection.disconnect();

                    Menu activity = (Menu) context;
                    activity.SetTextForTextView(textView, result.toString());


                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            return null;
        }
    }
}

最佳答案

AsyncTaskdoInBackground() 在另一个线程中运行,您无法从另一个线程更改 UI,只能从主线程更改 UI。我建议您在完成长期工作后在 onPostExecute() 中执行相同的工作。将要使用的字符串结果返回到主线程

bufferedReader.close();
inputStream.close();
httpURLConnection.disconnect();

// no need for that
//Menu activity = (Menu) context;
//activity.SetTextForTextView(textView, result.toString());

reutrn result;

然后更新文本

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    if(result != null){
        SetTextForTextView(textView, result);
    }
}

我建议从 here 阅读更多相关内容和 here

关于java - 使用 Asynctasks 将文本设置为多个 TextField 会导致应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36830262/

相关文章:

android - Amazon Cognito 和 Android SDK 的问题 NotAuthorizedException : Invalid login token

java - 遵循递归

java - 如何在 Hibernate 中持久化字符串列表?

java - 如何在jsp页面中获取mysql查询结果?

android - MockK 中的参数匹配器

android - ArrayAdapter 较晚从 AutoCompleteTextAdapter 中的 Webservice 更新

android - 在对话框内的 ListView 上执行 onclick 操作

java - 无法使用 jquery Ajax 从 Java HttpServer 获得响应

java - setText 未在 Runnable 中更新

android - MVVM带 Backstack 的跨选项卡导航