处理Android UI上的线程

时间:2011-11-18 12:22:48

标签: android android-asynctask handler

在我的应用程序中,我想检查设备上的网络状态,如果在设备上没有检测到网络连接,我想显示一个没有网络连接的Toast,然后退出应用程序。如果在设备上检测到连接,那么我必须从webservice加载一个列表并将其显示在屏幕上

我在应用程序的onCreate函数中完成了以下代码。它在模拟器上运行但在真实设备上运行。这在设备上显示ANR的原因是我试图在UI上处理这么多线程,这在android中不受欢迎。请使用AsyncTask指导我如何做到这一点。

任何代码段或指向教程或建议的链接都会对我有所帮助

boolean connected = false;
            ConnectivityManager connectivitymanager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkinfo = connectivitymanager.getActiveNetworkInfo();
            connected = networkinfo != null && networkinfo.isAvailable()
                    && networkinfo.isConnected();
            Log.v("Message ", connected + "");
            Log.v("Message ", networkinfo.getReason());
            //Toast.makeText(CategoryActivity.this, connected + "", 2000).show();
            //connected = false;
            Log.v("Message 1", connected + "");
            if (connected == false) {
                CategoryActivity.this.runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        // Log.v("Message ", connected + "");
                        Toast.makeText(CategoryActivity.this,
                                "No Internet Connection detected on device", 3000).show();
                    }
                });
                Handler handler1 = new Handler();
                handler1.postDelayed(new Thread(new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        finish();
                        System.exit(0);
                    }
                }), 4000);
            } else {
                CategoryArray = new JSONArray();
                final ProgressDialog pd = ProgressDialog.show(
                        CategoryActivity.this, "", "Loading...", false, true);
                pd.setIcon(getResources().getDrawable(R.drawable.icon));
                new Thread() {
                    public void run() {
                        try {
                            sleep(5000);
                            // Log.v("TAG","in try block");
                        } catch (Exception e) {
                            // Log.e("tag", e.getMessage());
                        }
                        pd.dismiss();
                        // Log.v("TAG","progress dismiss");
                    }
                }.start();

                handler.postDelayed(new Thread(new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        CategoryArray = CW
                                .getCategory("http://www.balajeebazaar.com/RestServiceImpl.svc/categorydetails");
                        // TODO: handle exception

                        for (int i = 0; i <= CategoryArray.length() - 1; i++) {
                            try {
                                String[] val = new String[3];
                                Log.v("category array : ",
                                        CategoryArray.getString(i));
                                val = CategoryArray.getString(i).split(",");
                                CategoryID.add(i, val[0]);
                                CategoryList.add(i, val[1]);
                                val = null;
                            } catch (JSONException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                        adapter = new CategoryListAdapter(CategoryActivity.this,
                                CategoryList);
                        list.setAdapter(adapter);
                    }
                }), 5000);

由于

修改

ERROR/AndroidRuntime(5486): Uncaught handler: thread AsyncTask #1 exiting due to uncaught exception

ERROR/AndroidRuntime(5486): java.lang.RuntimeException: An error occured while executing doInBackground()

ERROR/AndroidRuntime(5486):     at android.os.AsyncTask$3.done(AsyncTask.java:200)
ERROR/AndroidRuntime(5486):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:234)
ERROR/AndroidRuntime(5486):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:258)
ERROR/AndroidRuntime(5486):     at java.util.concurrent.FutureTask.run(FutureTask.java:122)
ERROR/AndroidRuntime(5486):     at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:648)
ERROR/AndroidRuntime(5486):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:673)
ERROR/AndroidRuntime(5486):     at java.lang.Thread.run(Thread.java:1060)
ERROR/AndroidRuntime(5486): Caused by: java.lang.ArrayIndexOutOfBoundsException
ERROR/AndroidRuntime(5486):     at com.ecommerce.balajeebazaar.CategoryActivity$Loader.doInBackground(CategoryActivity.java:181)
ERROR/AndroidRuntime(5486):     at com.ecommerce.balajeebazaar.CategoryActivity$Loader.doInBackground(CategoryActivity.java:1)
ERROR/AndroidRuntime(5486):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
11-18 18:30:07.582: ERROR/AndroidRuntime(5486): 
                        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:256)
ERROR/AndroidRuntime(5486):     4 more

3 个答案:

答案 0 :(得分:1)

我建议您在应用我在下面发布的解决方案之前先阅读AsyncTask,以便更好地了解正在发生的事情。

这是您Activity所需要的(它必须替换您发布的所有代码):

    boolean connected = false;
    ConnectivityManager connectivitymanager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkinfo = connectivitymanager.getActiveNetworkInfo();
    connected = networkinfo != null && networkinfo.isAvailable()
            && networkinfo.isConnected();
    Log.v("Message ", connected + "");
    Log.v("Message ", networkinfo.getReason());
    //Toast.makeText(CategoryActivity.this, connected + "", 2000).show();
    //connected = false;
    Log.v("Message 1", connected + "");
    if (connected == false) {
      Toast.makeText(CategoryActivity.this, "No Internet Connection detected on device", Toast.LENGTH_LONG ).show();
      finish();
    } else {
      new Loader().execute();
    }

这是AsyncTask,它应该是Activity的内部类:

    private class Loader extends AsyncTask<Void, Void, Void> {
      final ProgressDialog pd;

      @Override
      protected void onPreExecute() {
        pd = ProgressDialog.show( CategoryActivity.this, "", "Loading...", false, true);
        pd.setIcon(getResources().getDrawable(R.drawable.icon));
        super.onPreExecute();
      }

      @Override
      protected Void doInBackground( Void... arg0 ) {
        CategoryArray = new JSONArray();
        CategoryArray = CW.getCategory("http://www.balajeebazaar.com/RestServiceImpl.svc/categorydetails");

        for (int i = 0; i <= CategoryArray.length() - 1; i++) {
          try {
              String[] val = new String[3];
              Log.v("category array : ", CategoryArray.getString(i));
              val = CategoryArray.getString(i).split(",");
              CategoryID.add(i, val[0]);
              CategoryList.add(i, val[1]);
              val = null;
          } catch (JSONException e) {
            e.printStackTrace();
          }
        }

        adapter = new CategoryListAdapter(CategoryActivity.this, CategoryList);

        return null;
      }


      @Override
      protected void onPostExecute( Void result ) {
        pd.dismiss();
        list.setAdapter(adapter);
        super.onPostExecute( result );
      }
    }

注意

我无法检查上述内容是否真的有效 - 但它应该让你走上正轨。

答案 1 :(得分:0)

AsyncTasks和Handlers上的一个不错的tutorial

非常简短,AsyncTask的想法 - 你创建了一个私有类,它在你的Activity中扩展了AsyncTask。 这样做,您可以自动从AsyncTask类访问此活动UI线程。

在AsyncTaks中,您应该注意几种方法。它们被解释为here

你应该知道的是,只有doInBackground()在一个单独的线程中执行。其他所有内容都在Activity的UI线程上调用,其中定义了AsyncTask。

简单方案:

public class MyActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
     // stuff
   new MyAsyncTask().execute(); //this should be invoked only once
   }

   private class MyAsyncTask() extends AsyncTask<Void, Void, <TypeOfResult Or Void>> {

    @Override //executed on the UI thread of MyActivity
    protected void onPreExecute() {
        super.onPreExecute();
                   //prepare some stuff
            }

    @Override //executed in a separate Thread. This thread is automatically handled by AsyncTask
    protected <TypeOfResult or Void> doInBackground(Void... params) {

        //long operation
    }

            @Override //executed on the UI thread of MyActivity
    protected void onPostExecute(<TypeOf Result Or Void>) {
        super.onPostExecute(result);
                        // do stuff with result from long operation
    }
   }
}

答案 2 :(得分:0)

您不一定需要AsyncTask,您可以使用常规Java线程来完成您的需要(对于像这样的后台任务来说要容易得多)。