【问题标题】:java.lang.RuntimeException: Can't toast on a thread that has not called Looper.prepare() [duplicate]java.lang.RuntimeException:无法在尚未调用 Looper.prepare() 的线程上敬酒 [重复]
【发布时间】:2020-01-13 16:28:36
【问题描述】:

我正在按照 Udemy 的教程制作天气应用程序。这也是我第一次使用 JSON 数据,所以我不确定这是否会影响我的情况。但是,每次我运行我的应用程序时,它都会打开;当我按下应该显示给定城市天气的按钮时,应用程序崩溃了。

我研究了 Looper.prepare(),因为它包含在错误中,但是添加 looper 不起作用(我是编码新手,我可能做错了)我还尝试将 runOnUiThread(新 Runnable)添加到无济于事(再次,我可能做错了)。

    public class MainActivity extends AppCompatActivity {

    EditText editText;
    TextView resultTextView;

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

        editText = findViewById(R.id.editText);
        resultTextView = findViewById(R.id.resultTextView);

    }

    public void getWeather(View view) {
        try {
            DownloadTask task = new DownloadTask();
            String encodedCityName = 
URLEncoder.encode(editText.getText().toString(), "UTF-8");

            task.execute("http://openweathermap.org/data/2.5/weather?q=" 
+ encodedCityName + "&appid=b1b15e88fa797225412429c1c50c122a1");

            InputMethodManager mgr = (InputMethodManager) 
getSystemService(Context.INPUT_METHOD_SERVICE);
            mgr.hideSoftInputFromWindow(editText.getWindowToken(), 0);
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(getApplicationContext(), "Could not find 
weather :(", Toast.LENGTH_SHORT).show();
        }
    }

    public class DownloadTask extends AsyncTask<String, Void, String> {


        @Override
        protected String doInBackground(String... urls) {
            String result = "";
            URL url;
            HttpURLConnection urlConnection = null;
            try {

                url = new URL(urls[0]);
                urlConnection = (HttpURLConnection) url.openConnection();
                InputStream in = urlConnection.getInputStream();
                InputStreamReader reader = new InputStreamReader(in);
                int data = reader.read();

                while (data != -1) {
                    char current = (char) data;
                    result += current;
                    data = reader.read();
                }

                return result;

            } catch (Exception e) {
                e.printStackTrace();

                Toast.makeText(getApplicationContext(), "Could not find 
weather :(", Toast.LENGTH_SHORT).show();
                return null;
            }
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);

            Looper.prepare();
            try {
                JSONObject jsonObject = new JSONObject(s);

                String weatherInfo = jsonObject.getString("weather");

                Log.i("Weather content", weatherInfo);

                JSONArray arr = new JSONArray(weatherInfo);

                String message = "";

                for (int i = 0; i < arr.length(); i++) {
                    JSONObject jsonPart = arr.getJSONObject(i);

                  String main = jsonPart.getString("main");
                  String description = jsonPart.getString("description");

                    if (!main.equals("") && !description.equals("")) {
                        message += main + ": " + description + "\r\n";
                    }
                }

                if (!message.equals("")) {
                    resultTextView.setText(message);
                } else {
                    Toast.makeText(getApplicationContext(), "Could not 
                    find weather :(", Toast.LENGTH_SHORT).show();
                }

            } catch (Exception e) {

                Toast.makeText(getApplicationContext(), "Could not find 
                weather :(", Toast.LENGTH_SHORT).show();

                e.printStackTrace();
            }
        }
    }
}

这是我的 Logcat 中出现的错误

2019-09-11 13:24:52.431 
7574-7658/com.example.whatstheweather E/AndroidRuntime: FATAL EXCEPTION: 
AsyncTask #1

Process: com.example.whatstheweather, PID: 7574
java.lang.RuntimeException: An error occurred while executing 
doInBackground()
        at android.os.AsyncTask$4.done(AsyncTask.java:399)
        at 
    java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
    at java.util.concurrent.FutureTask.run(FutureTask.java:271)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)       atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) atjava.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:919)

Caused by: java.lang.RuntimeException: Can't toast on a thread that has 
not called Looper.prepare()
    at android.widget.Toast$TN.<init>(Toast.java:407)
    at android.widget.Toast.<init>(Toast.java:121)
    at android.widget.Toast.makeText(Toast.java:286)
    at android.widget.Toast.makeText(Toast.java:276)

atcom.example.whatstheweather.MainActivity$DownloadTask. 
doInBackground(MainActivity.java:81)
atcom.example.whatstheweather.MainActivity$DownloadTask. 
doInBackground(MainActivity.java:53)
    at android.os.AsyncTask$3.call(AsyncTask.java:378)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289) 
    atjava.util.concurrent.ThreadPoolExecutor. 
    runWorker(ThreadPoolExecutor.java:1167) 

atjava.util.concurrent.ThreadPoolExecutor$Worker. 
run(ThreadPoolExecutor.java:641) 
    at java.lang.Thread.run(Thread.java:919) 

以下内容来自“运行”标签

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.whatstheweather, PID: 11228
    java.lang.IllegalStateException: Could not execute method for 
    android:onClick
    at 
androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener. 
onClick(AppCompatViewInflater.java:390)
    at android.view.View.performClick(View.java:7140)
    at android.view.View.performClickInternal(View.java:7117)
    at android.view.View.access$3500(View.java:801)
    at android.view.View$PerformClick.run(View.java:27351)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller. 
run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
 Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Method.invoke(Native Method)
    at 
androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener. 
onClick(AppCompatViewInflater.java:385)
    at android.view.View.performClick(View.java:7140) 
    at android.view.View.performClickInternal(View.java:7117) 
    at android.view.View.access$3500(View.java:801) 
    at android.view.View$PerformClick.run(View.java:27351) 
    at android.os.Handler.handleCallback(Handler.java:883) 
    at android.os.Handler.dispatchMessage(Handler.java:100) 
    at android.os.Looper.loop(Looper.java:214) 
    at android.app.ActivityThread.main(ActivityThread.java:7356) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller. 
run(RuntimeInit.java:492) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 
 Caused by: java.lang.RuntimeException: Only one Looper may be created 
per thread
    at android.os.Looper.prepare(Looper.java:108)
    at android.os.Looper.prepare(Looper.java:103)
    at 
com.example.whatstheweather.MainActivity.getWeather(MainActivity.java:43)
    at java.lang.reflect.Method.invoke(Native Method) 
    at 
androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener. 
onClick(AppCompatViewInflater.java:385) 
    at android.view.View.performClick(View.java:7140) 
    at android.view.View.performClickInternal(View.java:7117) 
    at android.view.View.access$3500(View.java:801) 
    at android.view.View$PerformClick.run(View.java:27351) 
    at android.os.Handler.handleCallback(Handler.java:883) 
    at android.os.Handler.dispatchMessage(Handler.java:100) 
    at android.os.Looper.loop(Looper.java:214) 
    at android.app.ActivityThread.main(ActivityThread.java:7356) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller. 
run(RuntimeInit.java:492) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

【问题讨论】:

    标签: javascript java android android-studio toast


    【解决方案1】:

    问题是因为您的 toast 正在创建并显示在 doInBackground 方法中。在 android 用户界面操作必须在 UI 线程中处理。在 UI 线程中调用 onPostExecute 方法,但在另一个线程中调用方法 doInBackground。要解决您的问题,请从 doInBackground 方法中删除 Toast 并将以下几行放入 onPostExecute 方法中:

    // If s equals to null an error ocurred in doInBackground
    if (s == null) {
        Toast.makeText(getApplicationContext(), "Could not find weather :(",
                Toast.LENGTH_SHORT).show();
    }
    

    见:https://developer.android.com/training/multiple-threads/communicate-ui

    【讨论】:

      【解决方案2】:

      您的Toast.makeText 方法应该在主线程上调用。你可以这样做:

      runOnUiThread(new Runnable() {
          public void run() {
              Toast.makeText(getApplicationContext(), "Could not find weather :(", Toast.LENGTH_SHORT).show();
          }
      });
      

      【讨论】:

        猜你喜欢
        • 2021-10-06
        • 1970-01-01
        • 1970-01-01
        • 2013-06-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多