java.lang.RuntimeException:无法在尚未调用 Looper.prepare() 的线程上敬酒 [重复]
Posted
技术标签:
【中文标题】java.lang.RuntimeException:无法在尚未调用 Looper.prepare() 的线程上敬酒 [重复]【英文标题】:java.lang.RuntimeException: Can't toast on a thread that has not called Looper.prepare() [duplicate] 【发布时间】: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)
【问题讨论】:
【参考方案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();
);
【讨论】:
以上是关于java.lang.RuntimeException:无法在尚未调用 Looper.prepare() 的线程上敬酒 [重复]的主要内容,如果未能解决你的问题,请参考以下文章