0

我对 Android 比较陌生,我正在尝试遵循教程。

我用以下代码创建了一个小项目:

package com.example.revivaltimesv1;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.Activity;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

    private static final int LENGTH_LONG = 10;
    private TextView message;// = (TextView)findViewById(R.id.message);

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

        message = (TextView)findViewById(R.id.message);

        Log.i("mine", "TESTING ... TESTING!!!");

        ConnectivityManager conManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = conManager.getActiveNetworkInfo();
        if( networkInfo != null && networkInfo.isConnected() ){
            Toast.makeText(this, "Established Network Connection!", LENGTH_LONG).show();
            String stringURL = "http://178.79.128.76/GTK/node/7";
            new DownloadStuff().execute(stringURL);
//          new test().execute();
            //message.setText("WORKING");
        }else{
            Toast.makeText(this, "No Network Connection!", LENGTH_LONG).show();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

//}

/*    private class test extends AsyncTask<String, String, String>{
        @Override
        protected String doInBackground(String... params) {
            // TODO Auto-generated method stub
            return null;
        }
    }
*/
    private class DownloadStuff extends AsyncTask<String, String, String>{

        protected String doInBackground(String... url) {
            // TODO Auto-generated method stub
            Log.i("CHECK", "OUTSIDE");
            try{
                Log.i("CHECK", "SUCCESS: " + url[0]);
                downloadUrl(url[0]);
                Toast.makeText(getApplicationContext(), "WORKING !!!", LENGTH_LONG).show();
            }catch(IOException i){
                Log.i("CHECK", "NOT so successful");
                Toast.makeText(getApplicationContext(), "ERROR: unable to establish contact with URL", LENGTH_LONG).show();     
            }
            return null;
        }

        protected void onPostExecute(String result) {
            // TODO Auto-generated method stub
//          super.onPostExecute(result);
            message.setText("Hurray!");
        }

        // Given a URL, establishes an HttpUrlConnection and retrieves
        // the web page content as a InputStream, which it returns as
        // a string.
        private String downloadUrl(String myurl) throws IOException {
            InputStream is = null;
            // Only display the first 500 characters of the retrieved
            // web page content.
            int len = 500;

            try {
                URL url = new URL(myurl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(10000 /* milliseconds */);
                conn.setConnectTimeout(15000 /* milliseconds */);
                conn.setRequestMethod("GET");
                conn.setDoInput(true);
                // Starts the query
                conn.connect();
                int response = conn.getResponseCode();
                Log.d("DEBUG_TAG", "The response is: " + response);
                is = conn.getInputStream();

                // Convert the InputStream into a string
                String contentAsString = readIt(is, len);
                return contentAsString;

            // Makes sure that the InputStream is closed after the app is
            // finished using it.
            } finally {
                if (is != null) {
                    is.close();
                } 
            }
        }
        public String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {
            Reader reader = null;
            reader = new InputStreamReader(stream, "UTF-8");        
            char[] buffer = new char[len];
            reader.read(buffer);
            return new String(buffer);
        }
    }

}

该应用程序运行短暂,但随后崩溃给我以下反馈:

02-08 03:39:16.316: E/AndroidRuntime(5106): FATAL EXCEPTION: AsyncTask #1
02-08 03:39:16.316: E/AndroidRuntime(5106): java.lang.RuntimeException: An error occured while executing doInBackground()
02-08 03:39:16.316: E/AndroidRuntime(5106):     at android.os.AsyncTask$3.done(AsyncTask.java:200)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.lang.Thread.run(Thread.java:1102)
02-08 03:39:16.316: E/AndroidRuntime(5106): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
02-08 03:39:16.316: E/AndroidRuntime(5106):     at android.os.Handler.<init>(Handler.java:121)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at android.widget.Toast.<init>(Toast.java:68)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at android.widget.Toast.makeText(Toast.java:231)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at com.example.revivaltimesv1.MainActivity$DownloadStuff.doInBackground(MainActivity.java:74)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at com.example.revivaltimesv1.MainActivity$DownloadStuff.doInBackground(MainActivity.java:1)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
02-08 03:39:16.316: E/AndroidRuntime(5106):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
02-08 03:39:16.316: E/AndroidRuntime(5106):     ... 4 more

我查看了错误堆栈的底部,但... 4 more似乎隐藏了与我的代码相关的部分 - 我认为。

4

5 回答 5

1

您不能在非 ui 线程中显示 Toast 。

您可以向 UI 线程发布消息,并让 UI 线程处理该消息。

于 2013-02-08T03:51:42.987 回答
1

您不能在非 UI 线程中使用 Toast。您可以从 onPostExecute() 显示 toast,因为它是从 UI 线程调用的,但不能从 doInBackground() 显示,因为它在自己的线程中运行。

于 2013-02-08T03:53:00.643 回答
1

实际上,错误在 logcat 堆栈跟踪中清楚地显示:02-08 03:39:16.316: E/AndroidRuntime(5106): at com.example.revivaltimesv1.MainActivity$DownloadStuff.doInBackground(MainActivity.java:74)

理想情况下,任何Toasts/UI 功能都应在onPostExecute(). 但是如果你必须在 中做doInBackground(),把它放在 aRunnable中,如代码所示。

Runnable run = new Runnable() {

    @Override
    public void run() {
        Toast.makeText(getApplicationContext(), "WORKING !!!", LENGTH_LONG).show();

    }
}; MainActivity.this.runOnUiThread(run);

在此处阅读有关AsyncTasks的更多信息,特别是标题为The 4 Steps的部分

于 2013-02-08T03:51:11.147 回答
0

当您使用 Async Task 时,请确保它不在主线程上工作,因此您无法显示Toast.

AsyncTask类有五个方法

  • onPreExecute()— 此方法在后台处理开始之前在 UI 线程上运行。
  • doInBackground()—此方法在后台运行,是所有实际工作完成的地方。
  • publishProgress()——这个方法,从方法中调用doInBackground() ,周期性的通知UI线程后台进程的进度。此方法将信息发送到 UI 进程。
  • onProgressUpdate()— 只要 doInBackground()方法调用,此方法就会在 UI 线程上运行publishProgress()。此方法从后台进程接收信息。
  • onPostExecute()— 一旦后台处理完成,此方法在 UI 线程上运行。

因此,每当您想要执行诸如显示进程状态之类的操作时,您都应该使用OnProcessUpdate()方法,因为它允许您与主线程进行交互。

于 2013-02-08T03:56:38.937 回答
0

不要尝试Toast在后台线程中显示 a 。

private class DownloadStuff extends AsyncTask<String, String, String>{

        protected String doInBackground(String... url) {
            // TODO Auto-generated method stub
            Log.i("CHECK", "OUTSIDE");
            try{
                // ....
                Toast.makeText(getApplicationContext(), "WORKING !!!", LENGTH_LONG).show();
            }catch(IOException i){

                Toast.makeText(getApplicationContext(), "ERROR: unable to establish contact with URL", LENGTH_LONG).show();     
            }
            return null;
}
于 2013-02-08T03:50:12.897 回答