【问题标题】:Async DoInBackground Crashing under ListviewListview下的异步DoInBackground崩溃
【发布时间】:2012-04-10 20:53:48
【问题描述】:

我得到了一些 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)

【问题讨论】:

    标签: java android multithreading android-asynctask


    【解决方案1】:
    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;
        }
      }
    
    }
    

    【讨论】:

    • 即使我删除了这些行,它仍然会崩溃。
    • EDIT1:我看到你更新的评论,我还是看不懂代码。
    • 我再次尝试更新。基本上创建一个简单的容器,其中包括您的 List 和一些其他字段,如 loginerror 等。填充并将该模式​​从加载函数返回到 onpostexecute。
    • 我早上试试这个;如果它不起作用,我将重新编写 Async。
    • 我现在创建了一个测试项目并根据我的建议编辑了您的代码。检查我的最新代码,它会工作。
    【解决方案2】:
    Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    

    在doInbackground()中调用Looper.Prepare()

    编辑:还请确保您在 UI 线程上运行 Toast,正如其他人所指出的那样。

    【讨论】:

    • 我刚试过这个,它仍然崩溃。我应该用新的 logcat 更新线程吗?
    • 如果你添加了 Looper.Prepare() 并且它仍然崩溃,如果它是创建 vie 的线程错误,那么按照 kailoon 所说的并使用 runOnUIThread() 函数。
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      您在主 UI 线程中调用 Toast.makeText

      正如它在堆栈跟踪中所写的那样:

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

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

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

      发布进度(...);

      onProgressUpdate()

      可从 AsyncTasks 获得。

      【讨论】:

        猜你喜欢
        • 2012-03-14
        • 2017-12-22
        • 2015-07-02
        • 1970-01-01
        • 1970-01-01
        • 2013-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多