0

我是 android 的新手,我试图从服务器获取一些数据并将其打印到我的设备中。我意识到使用 android 4.x 我们无法做到这一点,因为 UI 线程被阻塞了。我进行了研究,发现了 AsyncTask。有人可以对我的代码提供一些帮助吗?有什么遗漏吗?谢谢

这是我的代码:

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

    new Thread().execute();        
    openDialog(getCurrentFocus());

}

异步任务类:

    private class Thread extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... params) {

               //Here i make a HTTP request.

         return null;
    }
   } 

日志猫:

04-22 22:43:10.808: E/Trace(12987): error opening trace file: No such file or directory (2)
04-22 22:43:11.098: E/AndroidRuntime(12987): FATAL EXCEPTION: AsyncTask #1

04-22 22:43:11.098: E/AndroidRuntime(12987): java.lang.RuntimeException: An error occured while executing doInBackground()
04-22 22:43:11.098: E/AndroidRuntime(12987):    at android.os.AsyncTask$3.done(AsyncTask.java:299)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at java.util.concurrent.FutureTask.run(FutureTask.java:239)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at java.lang.Thread.run(Thread.java:856)
04-22 22:43:11.098: E/AndroidRuntime(12987): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
04-22 22:43:11.098: E/AndroidRuntime(12987):    at android.os.Handler.<init>(Handler.java:197)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at android.os.Handler.<init>(Handler.java:111)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at android.widget.Toast$TN.<init>(Toast.java:324)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at android.widget.Toast.<init>(Toast.java:91)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at android.widget.Toast.makeText(Toast.java:238)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at com.application.uprm_map.MainActivity.startApplication(MainActivity.java:72)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at com.application.uprm_map.MainActivity.access$0(MainActivity.java:67)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at com.application.uprm_map.MainActivity$Thread.doInBackground(MainActivity.java:439)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at com.application.uprm_map.MainActivity$Thread.doInBackground(MainActivity.java:1)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at android.os.AsyncTask$2.call(AsyncTask.java:287)
04-22 22:43:11.098: E/AndroidRuntime(12987):    at java.util.concurrent.FutureTask.run(FutureTask.java:234)
04-22 22:43:11.098: E/AndroidRuntime(12987):    ... 3 more
04-22 22:43:11.413: E/WindowManager(12987): Activity com.application.uprm_map.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{421b4b58 V.E..... R.....I. 0,0-720,412} that was originally added here
04-22 22:43:11.413: E/WindowManager(12987): android.view.WindowLeaked: Activity com.application.uprm_map.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{421b4b58 V.E..... R.....I. 0,0-720,412} that was originally added here
04-22 22:43:11.413: E/WindowManager(12987):     at android.view.ViewRootImpl.<init>(ViewRootImpl.java:354)
04-22 22:43:11.413: E/WindowManager(12987):     at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:216)
4

1 回答 1

5

我附上了一个使用 AsyncTask 将参数发布到网页的示例(简化,它应该处理isCancelled一个)它应该不会太难适应您的需求。

AsyncTask 使用

AsyncTask 必须子类化才能使用。子类将覆盖至少一种方法(doInBackground(Params...)),并且通常会覆盖第二种方法(onPostExecute(Result)。)

AsyncTask 的泛型类型

异步任务使用的三种类型如下:

Params, 执行时发送给任务的参数类型。

Progress,在后台计算期间发布的进度单元的类型。

Result, 后台计算结果的类型。

并非所有类型都始终由异步任务使用。要将类型标记为未使用,只需使用类型 Void:

private class MyTask extends AsyncTask<Void, Void, Void> { ... }

4个步骤

当一个异步任务被执行时,任务会经过 4 个步骤:

  1. onPreExecute(),在任务执行之前在 UI 线程上调用。此步骤通常用于设置任务,例如通过在用户界面中显示进度条。
  2. doInBackground(Params...) ,在onPreExecute()完成执行后立即在后台线程上调用。此步骤用于执行可能需要很长时间的后台计算。异步任务的参数传递到这一步。计算的结果必须由这一步返回,并将传递回最后一步。此步骤还可以使用publishProgress(Progress...)来发布一个或多个进度单位。这些值在 UI 线程上的onProgressUpdate(Progress...)步骤中发布。
  3. onProgressUpdate(Progress...),在调用 publishProgress(Progress...) 后在 UI 线程上调用。执行的时间是不确定的。此方法用于在后台计算仍在执行时在用户界面中显示任何形式的进度。例如,它可用于动画进度条或在文本字段中显示日志。
  4. onPostExecute(Result),在后台计算完成后在 UI 线程上调用。后台计算的结果作为参数传递给该步骤。

在http://developer.android.com/reference/android/os/AsyncTask.html阅读有关 AsyncTask 的更多信息(以上文档取自以下链接)

POST 到网页的示例

// (declaration in main class)
private MyNetworkTask mMyNetworkTask = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    String mURL = "http://www.mydomain.com/mycode.php";
    runMyTask(this, mURL);
}

private class MyNetworkTask extends AsyncTask<String, Void, HttpResponse> { // <doInBackground, onProgressUpdate, onPostExecute>

    private ProgressDialog dialog;
    private Context context;

    public MyNetworkTask(Context ctx) {
        context = ctx;
        dialog = new ProgressDialog(context);
    }

    @Override
    protected void onPreExecute() {
        dialog.setMessage("Working ...");
        dialog.show();
    }
    @Override
    protected HttpResponse doInBackground(final String... params) {
        String mURL = params[0];
        HttpParams httpparams = new BasicHttpParams();
        HttpProtocolParams.setContentCharset(httpparams, "UTF-8");

        HttpClient httpclient = new DefaultHttpClient(httpparams);
        HttpPost httppost = new HttpPost(mURL);
        httppost.setHeader("User-Agent", "MyUserAgent/1.0");

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
        nameValuePairs.add(new BasicNameValuePair("param1", "value1"));
        nameValuePairs.add(new BasicNameValuePair("param2", "value2"));
        try {
            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            return httpclient.execute(httppost);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
    @Override
    protected void onPostExecute(final HttpResponse result) {
        if (dialog.isShowing()) {
            dialog.dismiss();
        }
        if (result != null) {
            int responseCode = result.getStatusLine().getStatusCode();
            String responseBody="";
            switch(responseCode) {
            case 200:
                HttpEntity entity = result.getEntity();
                if(entity != null) {
                    try {
                        responseBody = EntityUtils.toString(entity);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                break;
            }
            Log.v(TAG, "Response Code => " + responseCode);
            Log.i(TAG, "Response Body => " + responseBody);
        }
    }

    @Override
    protected void onCancelled() {
        if (dialog.isShowing()) {
            dialog.dismiss();
        }
    }
} // AsyncTask

private void runMyTask(Context ctx, String url) {
    if (mMyNetworkTask != null) {
            return;
        }
        mMyNetworkTask = new NetworkTask(this);
        mMyNetworkTask .execute(url);
}
于 2013-04-23T03:07:33.497 回答