javascript - java.lang.RuntimeException:不能在没有调用 Looper.prepare() 的线程上烤面包
问题描述
我正在按照 Udemy 的教程制作天气应用程序。这也是我第一次使用 JSON 数据,所以我不确定这是否会影响我的情况。但是,每次我运行我的应用程序时,它都会打开;当我按下应该显示给定城市天气的按钮时,应用程序崩溃了。
我研究了 Looper.prepare() ,因为它包含在错误中,但是添加 looper 不起作用(我是编码新手,我可能做错了)我还尝试添加 runOnUiThread (new 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)
解决方案
您的Toast.makeText
方法应该在主线程上调用。你可以这样做:
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "Could not find weather :(", Toast.LENGTH_SHORT).show();
}
});
推荐阅读
- python - 输入值并添加特定类型
- tsql - 拆分多个值,并将标题包含在列中
- javascript - 抱歉,我们这里没有图像 - Google 卫星地图
- opennms - 通过电子邮件/系统输出的 KSC 报告
- wordpress - 如何将类添加到忍者表单的隐藏字段和分隔符
- ios - WebSocket 消息是否缓存在 iOS 上?
- r - curl::curl_fetch_memory(url, handle = handle) 中的错误:已达到超时:发送失败:连接已重置
- java - Spring REST 控制器映射 JSON
- android - 如何使用 Retrofit2 解决空 Web 服务响应?
- javascript - 如何将 Int16Array 缓冲区保存到 wav 文件节点 js