【问题标题】:App crashes while can't perform AsyncTask应用程序在无法执行 AsyncTask 时崩溃
【发布时间】:2018-04-30 13:21:59
【问题描述】:

我的应用程序中的AsyncTask 有问题。 AsyncTask 位于SplashScreenAcivity.java。它使用 json 为 MainActivity.java 下载数据,同时显示启动画面。加载数据后,应用程序显示 MainActivity 屏幕。但是,当我关闭互联网连接应用程序崩溃。而不是它,我想转到MainActivity.java 并显示必须打开互联网连接的吐司。 SplashScreen.java 在 MainActivity 中为 listView 加载数据。

SplashActivityScreen.java

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

    new DownloadData().execute();

}

private class DownloadData extends AsyncTask<Void, Void, Void> {



    @Override
    protected Void doInBackground(Void... voids) {

                SyncHttpClient clientOne = new SyncHttpClient();
                clientOne.get("https://api.themoviedb.org/3/tv/top_rated?api_key=d253f520df9cd868af7db8daaa0db8fb&language=en-US", new JsonHttpResponseHandler() {

                    @Override
                    public void onSuccess(int statusCode, Header[] headers, JSONObject response) {

                        try {

                            tvseries0 = response.getJSONArray("results").getJSONObject(0).getString("name");
                            tvseries1 = response.getJSONArray("results").getJSONObject(1).getString("name");
                            tvseries2 = response.getJSONArray("results").getJSONObject(2).getString("name");
                            tvseries3 = response.getJSONArray("results").getJSONObject(3).getString("name");
                            tvseries4 = response.getJSONArray("results").getJSONObject(4).getString("name");
                            tvseries5 = response.getJSONArray("results").getJSONObject(5).getString("name");
                            tvseries6 = response.getJSONArray("results").getJSONObject(6).getString("name");
                            tvseries7 = response.getJSONArray("results").getJSONObject(7).getString("name");
                            tvseries8 = response.getJSONArray("results").getJSONObject(8).getString("name");
                            tvseries9 = response.getJSONArray("results").getJSONObject(9).getString("name");
                            tvseries10 = response.getJSONArray("results").getJSONObject(10).getString("name");
                            tvseries11 = response.getJSONArray("results").getJSONObject(11).getString("name");
                            tvseries12 = response.getJSONArray("results").getJSONObject(12).getString("name");
                            tvseries13 = response.getJSONArray("results").getJSONObject(13).getString("name");
                            tvseries14 = response.getJSONArray("results").getJSONObject(14).getString("name");
                            tvseries15 = response.getJSONArray("results").getJSONObject(15).getString("name");
                            tvseries16 = response.getJSONArray("results").getJSONObject(16).getString("name");
                            tvseries17 = response.getJSONArray("results").getJSONObject(17).getString("name");
                            tvseries18 = response.getJSONArray("results").getJSONObject(18).getString("name");
                            tvseries19 = response.getJSONArray("results").getJSONObject(19).getString("name");

                        } catch (JSONException e) {

                            e.printStackTrace();

                        }

                    }

                    @Override
                    public void onFailure(int statusCode, Header[] headers,Throwable e , JSONObject response) {

                        Toast.makeText(SplashScreenActivity.this, "Turn on the internet and swipe to refresh.", Toast.LENGTH_SHORT).show();

                    }
                });

        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);

        Intent i = new Intent(getApplicationContext(), MainActivity.class);

        i.putExtra("tvseries0", tvseries0);
        i.putExtra("tvseries1", tvseries1);
        i.putExtra("tvseries2", tvseries2);
        i.putExtra("tvseries3", tvseries3);
        i.putExtra("tvseries4", tvseries4);
        i.putExtra("tvseries5", tvseries5);
        i.putExtra("tvseries6", tvseries6);
        i.putExtra("tvseries7", tvseries7);
        i.putExtra("tvseries8", tvseries8);
        i.putExtra("tvseries9", tvseries9);
        i.putExtra("tvseries10", tvseries10);
        i.putExtra("tvseries11", tvseries11);
        i.putExtra("tvseries12", tvseries12);
        i.putExtra("tvseries13", tvseries13);
        i.putExtra("tvseries14", tvseries14);
        i.putExtra("tvseries15", tvseries15);
        i.putExtra("tvseries16", tvseries16);
        i.putExtra("tvseries17", tvseries17);
        i.putExtra("tvseries18", tvseries18);
        i.putExtra("tvseries19", tvseries19);

        startActivity(i);

        finish();

    }
}

}

崩溃 1

04-30 13:15:35.165 12349-12365/przemo.me.recommend.recommendme E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: przemo.me.recommend.recommendme, PID: 12349
java.lang.RuntimeException: An error occurred while executing doInBackground()
    at android.os.AsyncTask$3.done(AsyncTask.java:318)
    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
    at java.lang.Thread.run(Thread.java:761)
 Caused by: java.lang.RuntimeException: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    at com.loopj.android.http.AsyncHttpResponseHandler.onUserException(AsyncHttpResponseHandler.java:304)
    at com.loopj.android.http.AsyncHttpResponseHandler.handleMessage(AsyncHttpResponseHandler.java:395)
    at com.loopj.android.http.AsyncHttpResponseHandler.sendMessage(AsyncHttpResponseHandler.java:401)
    at com.loopj.android.http.AsyncHttpResponseHandler.sendFailureMessage(AsyncHttpResponseHandler.java:319)
    at com.loopj.android.http.AsyncHttpRequest.run(AsyncHttpRequest.java:109)
    at com.loopj.android.http.SyncHttpClient.sendRequest(SyncHttpClient.java:95)
    at com.loopj.android.http.AsyncHttpClient.get(AsyncHttpClient.java:1078)
    at com.loopj.android.http.AsyncHttpClient.get(AsyncHttpClient.java:1037)
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData.doInBackground(SplashScreenActivity.java:64)
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData.doInBackground(SplashScreenActivity.java:56)
    at android.os.AsyncTask$2.call(AsyncTask.java:304)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
    at java.lang.Thread.run(Thread.java:761) 
 Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    at android.os.Handler.<init>(Handler.java:200)
    at android.os.Handler.<init>(Handler.java:114)
    at android.widget.Toast$TN.<init>(Toast.java:346)
    at android.widget.Toast.<init>(Toast.java:101)
    at android.widget.Toast.makeText(Toast.java:260)
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData$1.onFailure(SplashScreenActivity.java:103)
    at com.loopj.android.http.JsonHttpResponseHandler.onFailure(JsonHttpResponseHandler.java:233)
    at com.loopj.android.http.AsyncHttpResponseHandler.handleMessage(AsyncHttpResponseHandler.java:359)
    at com.loopj.android.http.AsyncHttpResponseHandler.sendMessage(AsyncHttpResponseHandler.java:401) 
    at com.loopj.android.http.AsyncHttpResponseHandler.sendFailureMessage(AsyncHttpResponseHandler.java:319) 
    at com.loopj.android.http.AsyncHttpRequest.run(AsyncHttpRequest.java:109) 
    at com.loopj.android.http.SyncHttpClient.sendRequest(SyncHttpClient.java:95) 
    at com.loopj.android.http.AsyncHttpClient.get(AsyncHttpClient.java:1078) 
    at com.loopj.android.http.AsyncHttpClient.get(AsyncHttpClient.java:1037) 
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData.doInBackground(SplashScreenActivity.java:64) 
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData.doInBackground(SplashScreenActivity.java:56) 
    at android.os.AsyncTask$2.call(AsyncTask.java:304) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
    at java.lang.Thread.run(Thread.java:761) 

崩溃 2

04-30 13:15:35.162 12349-12365/przemo.me.recommend.recommendme E/AsyncHttpRH: User-space exception detected!
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    at android.os.Handler.<init>(Handler.java:200)
    at android.os.Handler.<init>(Handler.java:114)
    at android.widget.Toast$TN.<init>(Toast.java:346)
    at android.widget.Toast.<init>(Toast.java:101)
    at android.widget.Toast.makeText(Toast.java:260)
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData$1.onFailure(SplashScreenActivity.java:103)
    at com.loopj.android.http.JsonHttpResponseHandler.onFailure(JsonHttpResponseHandler.java:233)
    at com.loopj.android.http.AsyncHttpResponseHandler.handleMessage(AsyncHttpResponseHandler.java:359)
    at com.loopj.android.http.AsyncHttpResponseHandler.sendMessage(AsyncHttpResponseHandler.java:401)
    at com.loopj.android.http.AsyncHttpResponseHandler.sendFailureMessage(AsyncHttpResponseHandler.java:319)
    at com.loopj.android.http.AsyncHttpRequest.run(AsyncHttpRequest.java:109)
    at com.loopj.android.http.SyncHttpClient.sendRequest(SyncHttpClient.java:95)
    at com.loopj.android.http.AsyncHttpClient.get(AsyncHttpClient.java:1078)
    at com.loopj.android.http.AsyncHttpClient.get(AsyncHttpClient.java:1037)
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData.doInBackground(SplashScreenActivity.java:64)
    at przemo.me.recommend.recommendme.SplashScreenActivity$DownloadData.doInBackground(SplashScreenActivity.java:56)
    at android.os.AsyncTask$2.call(AsyncTask.java:304)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
    at java.lang.Thread.run(Thread.java:761)

【问题讨论】:

标签: java android json android-asynctask


【解决方案1】:

您不能从非 UI 线程执行 UI 操作。就像在您的代码中一样,您在异步任务线程中显示 Toast。

你应该替换

Toast.makeText(SplashScreenActivity.this, "Turn on the internet and swipe to refresh.", Toast.LENGTH_SHORT).show();     

有了这个

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(SplashScreenActivity.this, "Turn on the internet and swipe to refresh.", Toast.LENGTH_SHORT).show();     
        }
    });

【讨论】:

  • 它显示了消息,但是当我打算移动到 MainActivity.java 时它仍然崩溃
  • 我看过你的代码。您的代码可以有很多改进。就像你为什么需要 asyncTask 一样。 SyncHttpClient不负责后台线程下载数据吗?
  • 你是对的。我删除了 AsyncTask。但是,当我想移动到包含列表视图的 MainActivity.java 时,应用程序仍然崩溃。我收到一个错误:“尝试在空对象引用上调用虚拟方法 'java.lang.String java.lang.Object.toString()'”
  • 很明显你的一些对象是空的,你正试图进一步使用它。发布您的堆栈跟踪,您将获得一个行号和为空的对象。
【解决方案2】:

使用-

SplashScreenActivity.this.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(SplashScreenActivity.this, "Turn on the internet and swipe to refresh.", Toast.LENGTH_SHORT).show();     
        }
    });

【讨论】:

    【解决方案3】:

    这是我多年前在 Android Java 中创建的服务器连接 AsyncTask 任务。后台任务成功运行。我用它在后台更新了我当时开发的 App 中的数据存储库。

    public class DataExchangeStore extends Application {
        public void startServerConnection(Context contextGlobal, Activity activityGlobal) {
            this.contextGlobal = contextGlobal;
            this.activityGlobal = activityGlobal;
            connectTask = new ConnectTask();
            connectTask.execute("");
        }
    
        private ConnectTask connectTask;
    
        public class ConnectTask extends AsyncTask<String, String, TCPClient> {
            @Override
            protected TCPClient doInBackground(String... message) {
                android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_BACKGROUND);
                // we create a TCPClient object
                mTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {
                    @Override
                    // here the messageReceived method is implemented
                    public void messageReceived(ChatMessage message) {
                        // this method calls the onProgressUpdate
                        publishProgress(message.getMessage());
                    }
                }, contextGlobal, activityGlobal);
                mTcpClient.run();
                return null;
            }
            @Override
            protected void onProgressUpdate(String... values) {
                super.onProgressUpdate(values);
                System.err.println(values[0]);
                // do your stuff here
            }
        }
    

    导入是永久锁定activity的屏幕方向,在Android-Manifest文件中用portraitlandscape指定screenOrientation属性价值观:

    <activity android:screenOrientation="portrait" />
    

    【讨论】:

      【解决方案4】:

      虽然前面的回答没有错,但是在AsyncTask中使用runOnUiThread()跳出后台线程并不是一个好的做法。你有 onPostExecute() 方法。

      您应该做的是将结果对象传递给onPostExecute()。该对象将封装结果状态(即:错误或成功)和接收到的实际数据。然后在onPostExecute() 中检查结果状态,如果状态为错误,则显示 Toast。

      帮自己一个忙,将 20 个 TvSerie 对象替换为 List&lt;TvSerie&gt;,并在 AsyncTask 中执行循环以填充列表。

      如何正确使用请参考the AsyncTask documentation

      【讨论】:

      • 能否请您澄清一下如何将结果对象准确地传递给 onPostExecute()?
      • 我添加了asynctask官方文档的链接。你应该阅读它。
      猜你喜欢
      • 2018-02-25
      • 1970-01-01
      • 2019-09-08
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多