从互联网上检索数据阻止了主线程

时间:2013-10-28 12:42:46

标签: android multithreading

我想写一个Android应用程序,它将从互联网上检索数据并保存在本地文件中。这就是我写的:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Runnable r = new Runnable() {
        @Override
        public void run() {
            updateData();
        }
    };
    Handler h = new Handler();
    h.post(r);
}
private Boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager)
    getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo ni = cm.getActiveNetworkInfo();
    if(ni != null && ni.isConnectedOrConnecting()) {
        return true;
    }
    else {
        return false;
    }
}

private void updateData() {
    if(!isOnline()) {
        Toast.makeText(this, "Unable to update data: Internet Connection Unavailable", Toast.LENGTH_SHORT).show();
    }
    else {
        try {
            HttpClient client = new DefaultHttpClient();
            HttpGet req = new HttpGet("***SOME URL****");
            HttpResponse res = client.execute(req);             
            InputStream is = res.getEntity().getContent();
            InputStreamReader ir = new InputStreamReader(is);
            StringBuilder sb = new StringBuilder();
            Boolean end = false;
            do {
                int t = ir.read();
                if(t==-1) {
                    end = true;
                }
                else {
                    sb.append((char)t);
                }
            }
            while(!end);
            String s = sb.toString();
            File f = new File(getFilesDir(), "data.txt");
            FileWriter fw = new FileWriter(f);
            fw.write(s);
            fw.close();
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}

我让主线程被阻挡了大约2-3秒。而且我不确定这是否是正确的方法。因此,如果您认为这是一种不正确的方法,请随时告诉我。

此致 Sarun

2 个答案:

答案 0 :(得分:1)

来自处理程序构造函数API

  

将此处理程序与当前线程的Looper相关联。

这意味着您创建的Handler与UI线程的Looper相关联,这意味着正在UI线程上执行runnable(因此您会看到暂停的UI)。 我建议您使用Android的AsyncTask或在后台线程上实例化Handler

答案 1 :(得分:0)

使用AsyncTask来摆脱这个问题。 AsyncTask的代码如下:

class AsyncLogin extends AsyncTask<Void, Void, String> {
        ProgressDialog dialog = new ProgressDialog(MyTopic.this);

        protected String doInBackground(Void... params) {


            return msg;
        }

        protected void onPostExecute(String result) {
            try {

                    dialog.cancel();

                }
            } catch (Exception e) {
                dialog.cancel();
            }

        }

        protected void onPreExecute() {
            super.onPreExecute();
            dialog.setMessage("Fetching...Topic List!!!");
            dialog.setCancelable(true);
            dialog.show();

        }
    }

调用代码:

AsyncLogin as = new AsyncLogin();
as.execute();