Listview下的异步DoInBackground崩溃

时间:2012-04-10 20:53:48

标签: java android multithreading android-asynctask

我得到了一些stackflower的代码,由于某种原因,它崩溃了我的应用程序,是Async的新手,我没有很多调试经验。我尝试从HttPost下载数据,然后在简单的列表视图中列出数据。无论如何,这里是代码和logcat:

代码:

public class ChatService extends ListActivity {
    /** Called when the activity is first created. */

    BufferedReader in = null;
    String data = null;
    List headlines;
    List links;
    String GotPass;
    ArrayAdapter adapter;
    String GotUname;
    public static final String PREFS_NAME ="MyPregs";
    private GetTask getTask;
    public ListView fList;

    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
      getTask = new GetTask(); 
      getTask.execute();

      ArrayAdapter adapter = new ArrayAdapter(this,
              android.R.layout.simple_list_item_1, headlines);
    }

    public class GetTask extends AsyncTask<Void, Void, List> 
    {
      @Override
      protected List doInBackground(Void... params) {
        return load();
      }      

      @Override
      protected void onPostExecute(List result) {


        fList.setAdapter(adapter);
      }
    }

    private List load() { 
      // get your data from http
      // add to your list, probably you can use model.
        BufferedReader in = null;
        String data = null;
        Bundle gotData = getIntent().getExtras();
        if(gotData != null)
        {
            GotPass = gotData.getString("key!");
            GotUname = gotData.getString("key!!");
        }
        SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
        String username = settings.getString("key1", null);
        String password = settings.getString("key2", null);
         if(username.equals("irock97")) {
            Toast.makeText(getApplicationContext(), "yaya", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(getApplicationContext(), "fail", Toast.LENGTH_SHORT).show();
        }

        HttpClient httpclient = new DefaultHttpClient();

        /* login.php returns true if username and password is equal to saranga */
        HttpPost httppost = new HttpPost("http://gta5news.com/login.php");

        try {
            // Add user name and password
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
            nameValuePairs.add(new BasicNameValuePair("username", username));
            nameValuePairs.add(new BasicNameValuePair("password", password));
            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            // Execute HTTP Post Request
            Log.w("HttpPost", "Execute HTTP Post Request");
            HttpResponse response = httpclient.execute(httppost);
            in = new BufferedReader(new InputStreamReader(response.getEntity()
                    .getContent()));
            StringBuffer sb = new StringBuffer("");
            String l ="";
            String nl ="";
            while ((l =in.readLine()) !=null) {
                sb.append(l + nl);  
            }
            in.close();
             data = sb.toString();

             ListView lv = getListView();
             lv.setTextFilterEnabled(true);

            headlines.add(data);




            ArrayAdapter adapter = new ArrayAdapter(this,
                    android.R.layout.simple_list_item_1, headlines);

            setListAdapter(adapter);


        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return headlines;
    }

    private StringBuilder inputStreamToString1(InputStream is) {
        String line = "";
        StringBuilder total = new StringBuilder();
        // Wrap a BufferedReader around the InputStream
        BufferedReader rd = new BufferedReader(new InputStreamReader(is));
        // Read response until the end
        try {
            while ((line = rd.readLine()) != null) {
                total.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // Return full string
        return total;
    }




    }

logcat的:

04-10 20:47:18.526: E/AndroidRuntime(574): FATAL EXCEPTION: AsyncTask #1
04-10 20:47:18.526: E/AndroidRuntime(574): java.lang.RuntimeException: An error occured while executing doInBackground()
04-10 20:47:18.526: E/AndroidRuntime(574):  at android.os.AsyncTask$3.done(AsyncTask.java:200)
04-10 20:47:18.526: E/AndroidRuntime(574):  at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
04-10 20:47:18.526: E/AndroidRuntime(574):  at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
04-10 20:47:18.526: E/AndroidRuntime(574):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
04-10 20:47:18.526: E/AndroidRuntime(574):  at java.util.concurrent.FutureTask.run(FutureTask.java:137)
04-10 20:47:18.526: E/AndroidRuntime(574):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
04-10 20:47:18.526: E/AndroidRuntime(574):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
04-10 20:47:18.526: E/AndroidRuntime(574):  at java.lang.Thread.run(Thread.java:1096)
04-10 20:47:18.526: E/AndroidRuntime(574): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
04-10 20:47:18.526: E/AndroidRuntime(574):  at android.os.Handler.<init>(Handler.java:121)
04-10 20:47:18.526: E/AndroidRuntime(574):  at android.widget.Toast.<init>(Toast.java:68)
04-10 20:47:18.526: E/AndroidRuntime(574):  at android.widget.Toast.makeText(Toast.java:231)
04-10 20:47:18.526: E/AndroidRuntime(574):  at com.gta5news.bananaphone.ChatService.load(ChatService.java:97)
04-10 20:47:18.526: E/AndroidRuntime(574):  at com.gta5news.bananaphone.ChatService.access$0(ChatService.java:82)
04-10 20:47:18.526: E/AndroidRuntime(574):  at com.gta5news.bananaphone.ChatService$GetTask.doInBackground(ChatService.java:71)
04-10 20:47:18.526: E/AndroidRuntime(574):  at com.gta5news.bananaphone.ChatService$GetTask.doInBackground(ChatService.java:1)
04-10 20:47:18.526: E/AndroidRuntime(574):  at android.os.AsyncTask$2.call(AsyncTask.java:185)
04-10 20:47:18.526: E/AndroidRuntime(574):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)

4 个答案:

答案 0 :(得分:2)

You are calling Toast in load() function which is in DoInBackground. 
Toast messages touches UI thread which you can't do that.

This line makes it crash.
Toast.makeText(getApplicationContext(), "yaya", Toast.LENGTH_SHORT).show();

Change you load function signature:
This is your function:
private List load() {

don't return a list, create a modal container and return it like:
private ReturnModel load() {

and create a modal like this, and set and get this modal:
and in your load function,fill this returnmodal, set passworderror true or false instead of toast message, and onpostexecute function, check password error and do your toast message there.




package com.nesim.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.app.ListActivity;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class ChatService extends ListActivity {
  String GotPass;
  String GotUname;
  public static final String PREFS_NAME = "MyPregs";
  private GetTask getTask;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getTask = new GetTask();
    getTask.execute();
  }

  public class GetTask extends AsyncTask<Void, Void, ReturnModel> {
    @Override
    protected ReturnModel doInBackground(Void... params) {
      return load();
    }

    @Override
    protected void onPostExecute(ReturnModel result) {

      if(result.passworderror == true)
      {
        Toast.makeText(getApplicationContext(), "fail", Toast.LENGTH_SHORT).show();
      }
      else
      {
        Toast.makeText(getApplicationContext(), "yaya", Toast.LENGTH_SHORT).show();

        ListView lv = getListView();
        lv.setTextFilterEnabled(true);

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, result.getheadlines());
        setListAdapter(adapter);
      }
    }
  }

  private ReturnModel load() {
    ReturnModel returnModel = new ReturnModel();

    BufferedReader in = null;
    String data = null;
    Bundle gotData = getIntent().getExtras();
    if (gotData != null) {
      GotPass = gotData.getString("key!");
      GotUname = gotData.getString("key!!");
    }

    SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
    String username = settings.getString("key1", null);
    String password = settings.getString("key2", null);
    // username = "irock97"; // unremark to test like you got username from prefs..
    if (username != null  && username.equals("irock97")) {
      returnModel.setPassworderror(false);
    }
    else 
    {
      returnModel.setPassworderror(true);
      return returnModel;
    }

    HttpClient httpclient = new DefaultHttpClient();

    /* login.php returns true if username and password is equal to saranga */
    HttpPost httppost = new HttpPost("http://gta5news.com/login.php");

    try {
      // Add user name and password
      List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
      nameValuePairs.add(new BasicNameValuePair("username", username));
      nameValuePairs.add(new BasicNameValuePair("password", password));
      httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

      // Execute HTTP Post Request
      Log.w("HttpPost", "Execute HTTP Post Request");
      HttpResponse response = httpclient.execute(httppost);
      in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
      StringBuffer sb = new StringBuffer("");
      String l = "";
      String nl = "";
      while ((l = in.readLine()) != null) {
        sb.append(l + nl);
      }
      in.close();
      data = sb.toString();


      List<String> headlines = new ArrayList<String>();
      headlines.add(data);
      returnModel.setheadlines(headlines);
    }
    catch (ClientProtocolException e) {
      e.printStackTrace();
    }
    catch (IOException e) {
      e.printStackTrace();
    }

    return returnModel;
  }


  public class ReturnModel {
    private List<String> headlines;
    private boolean passworderror;

    public List<String> getheadlines() {
      return headlines;
    }

    public void setheadlines(List<String> headlines) {
      this.headlines = headlines;
    }

    public boolean getPassworderror() {
      return passworderror;
    }

    public void setPassworderror(boolean passworderror) {
      this.passworderror = passworderror;
    }
  }

}

答案 1 :(得分:0)

Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

在doInbackground()

中调用Looper.Prepare()

编辑:还要确保在UI线程上运行Toast,就像其他人都注意到的那样。

答案 2 :(得分:0)

当您尝试修改UI线程外部的UI时,通常会发生此错误。您看到的错误是由Toast.makeText()电话引起的。您可以将其重写为:

runOnUiThread(new Runnable() {
    public void run() {
        Toast.makeText( /* etc */).show();
    }
}

答案 3 :(得分:0)

您正在调用Toast.makeText而不是在主UI线程中。

因为它写在堆栈跟踪中:

无法在未调用Looper.prepare()的线程内创建处理程序。 在内部,Toast.makeText正在创建自己使用的处理程序。

如果这是出于测试目的,您最好使用Log.v或类似的。

如果你想真正制作Toasts,那么尝试使用runOnUIThread()或更好:

  

publishProgress(...);

  

onProgressUpdate()

可从AsyncTasks获得。