片段内部类错误抛出使用AsyncTask更新UI视图的致命异常

时间:2015-08-20 07:02:37

标签: java android android-asynctask

下面是我使用内部类Fragment的代码。我也使用AsyncTask来执行一些后台操作。它在执行时抛出致命异常。

public class LocationFragment extends Fragment {
        // Progress Dialog
        private ProgressDialog pDialog;
        // JSON parser class
        JSONParser jsonParser = new JSONParser();
        //gps class
        GPSTracker gps;
        double latitude,longitude;
        public TextView current_location;


        private static final String BC_URL = "http://manfredinfotech.com/projects/workshop/get_location.php";
        //JSON element ids from repsonse of php script:
        private static final String TAG_SUCCESS = "success";
        private static final String TAG_MESSAGE = "message";

        public LocationFragment(){}
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {

            // create class object
            gps = new GPSTracker(getActivity());

            // check if GPS enabled

            View rootView = inflater.inflate(R.layout.fragment_location, container, false);
            current_location = (TextView) rootView.findViewById(R.id.current_location);
            if (gps.canGetLocation()) {
                latitude = gps.getLatitude();
                longitude = gps.getLongitude();
                // \n is for new line
                Toast.makeText(getActivity(), "Your Location is - \nLat: " + latitude + "\nLong: " + longitude, Toast.LENGTH_LONG).show();
                new GetLocation().execute();
            }

            return rootView;
        }

        class GetLocation extends AsyncTask<String, String, String> {

            @Override
            protected void onPreExecute(){
                super.onPreExecute();
                pDialog = new ProgressDialog(getActivity());
                pDialog.setMessage("Processing...");
                pDialog.setIndeterminate(false);
                pDialog.setCancelable(true);
                pDialog.show();

            }
            @Override
            protected String doInBackground(String... args){
                int success;
                try{
                    List<NameValuePair> params = new ArrayList<NameValuePair>();
                    params.add(new BasicNameValuePair("lat",String.valueOf(latitude)));
                    params.add(new BasicNameValuePair("lon", String.valueOf(longitude)));


                    JSONObject json = jsonParser.makeHttpRequest(BC_URL, "POST", params);
                    System.out.println("JSON" + json);
                    // check your log for json response
                    Log.d("Here", json.toString());

                    success = json.getInt(TAG_SUCCESS);

                    if(success == 1){
                        if(pDialog.isShowing())pDialog.dismiss();
                        System.out.println(json.getString(TAG_MESSAGE));


                        current_location.setText(json.getString(TAG_MESSAGE));
                        //return json.getString(TAG_MESSAGE);
                    } else {
                        if(pDialog.isShowing())pDialog.dismiss();
                        current_location.setText("Not location found");
                        System.out.println("Failed!");
                        //return json.getString(TAG_MESSAGE);
                    }
                }
                catch (JSONException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }

    }

现在这一行current_location.setText(json.getString(TAG_MESSAGE)); 抛出错误。下面是我得到的例外的Stacktrace。

 > 08-20 12:30:44.242  27109-27190/com.mipl.trupco E/AndroidRuntime﹕
> FATAL EXCEPTION: AsyncTask #1
>     Process: com.mipl.trupco, PID: 27109
>     java.lang.RuntimeException: An error occured while executing doInBackground()
>             at android.os.AsyncTask$3.done(AsyncTask.java:304)
>             at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
>             at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
>             at java.util.concurrent.FutureTask.run(FutureTask.java:242)
>             at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
>             at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
>             at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
>             at java.lang.Thread.run(Thread.java:818)
>      Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the
> original thread that created a view hierarchy can touch its views.
>             at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6357)
>             at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:874)
>             at android.view.View.requestLayout(View.java:17476)
>             at android.view.View.requestLayout(View.java:17476)
>             at android.view.View.requestLayout(View.java:17476)
>             at android.view.View.requestLayout(View.java:17476)
>             at android.support.v4.widget.DrawerLayout.requestLayout(DrawerLayout.java:749)
>             at android.view.View.requestLayout(View.java:17476)
>             at android.view.View.requestLayout(View.java:17476)
>             at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
>             at android.view.View.requestLayout(View.java:17476)
>             at android.widget.TextView.checkForRelayout(TextView.java:6871)
>             at android.widget.TextView.setText(TextView.java:4057)
>             at android.widget.TextView.setText(TextView.java:3915)
>             at android.widget.TextView.setText(TextView.java:3890)
>             at com.mipl.trupco.LocationFragment$GetLocation.doInBackground(LocationFragment.java:99)
>             at com.mipl.trupco.LocationFragment$GetLocation.doInBackground(LocationFragment.java:65)
>             at android.os.AsyncTask$2.call(AsyncTask.java:292)
>             at java.util.concurrent.FutureTask.run(FutureTask.java:237)
>             at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
>             at 

请帮忙

3 个答案:

答案 0 :(得分:0)

您必须将更新ui的后台任务部分移动到主线程。有一段简单的代码:

runOnUiThread(new Runnable() {
     @Override
     public void run() {

//Update your UI

    }
});

Activity.runOnUiThread

或者您可以在Asynctask的onPostExecute中编写代码。

答案 1 :(得分:0)

您正在操作布局,即后台线程(doInBackground)中的current_location textview。这是不允许的,错误说明了这一点。对于操作视图元素,您应该使用onPreExecute或onPostExecute方法。

答案 2 :(得分:0)

错误在doInBackground()success == 1,因为您尝试从线程编辑文本视图current_location。 如此简单的解决方案是覆盖onPostExecute()类中的GetLocation方法,返回您想要的文本,并在那里设置它。在doInBackground()

中修改此内容
if(success == 1){
    if(pDialog.isShowing())pDialog.dismiss();
    System.out.println(json.getString(TAG_MESSAGE));
    return json.getString(TAG_MESSAGE);
} else {
    if(pDialog.isShowing())pDialog.dismiss();
    System.out.println("Failed!");
    return "Not location found";
}

并将此新方法添加到doInBackground()

之后
@Override
protected void onPostExecute(String result) {
    if(result != null)
        current_location.setText(result);
}