如何将数据从AsyncTask返回到主线程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何将数据从AsyncTask返回到主线程相关的知识,希望对你有一定的参考价值。

我想将Jsonobject返回到主线程。但是,当我尝试运行代码时,它返回以下错误。

02-06 06:14:36.490: E/androidRuntime(769): FATAL EXCEPTION: main
02-06 06:14:36.490: E/AndroidRuntime(769): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.dataread/com.example.dataread.MainActivity}: java.lang.NullPointerException
02-06 06:14:36.490: E/AndroidRuntime(769):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
02-06 06:14:36.490: E/AndroidRuntime(769):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
02-06 06:14:36.490: E/AndroidRuntime(769):  at android.app.ActivityThread.access$600(ActivityThread.java:141)
02-06 06:14:36.490: E/AndroidRuntime(769):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
02-06 06:14:36.490: E/AndroidRuntime(769):  at android.os.Handler.dispatchMessage(Handler.java:99)
02-06 06:14:36.490: E/AndroidRuntime(769):  at android.os.Looper.loop(Looper.java:137)
02-06 06:14:36.490: E/AndroidRuntime(769):  at android.app.ActivityThread.main(ActivityThread.java:5039)
02-06 06:14:36.490: E/AndroidRuntime(769):  at java.lang.reflect.Method.invokeNative(Native Method)
02-06 06:14:36.490: E/AndroidRuntime(769):  at java.lang.reflect.Method.invoke(Method.java:511)
02-06 06:14:36.490: E/AndroidRuntime(769):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
02-06 06:14:36.490: E/AndroidRuntime(769):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
02-06 06:14:36.490: E/AndroidRuntime(769):  at dalvik.system.NativeStart.main(Native Method)
02-06 06:14:36.490: E/AndroidRuntime(769): Caused by: java.lang.NullPointerException
02-06 06:14:36.490: E/AndroidRuntime(769):  at com.example.dataread.MainActivity.onCreate(MainActivity.java:37)
02-06 06:14:36.490: E/AndroidRuntime(769):  at android.app.Activity.performCreate(Activity.java:5104)
02-06 06:14:36.490: E/AndroidRuntime(769):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
02-06 06:14:36.490: E/AndroidRuntime(769):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
02-06 06:14:36.490: E/AndroidRuntime(769):  ... 11 more

这是我的代码:

public interface Asynchtask 
{
void processFinish(JSONObject result);

}


public class MainActivity extends ListActivity implements Asynchtask 
{

    JSONfunctions js= new JSONfunctions();
    JSONObject retunfromAsyncTask;
    //public static JSONObject dataFromAsyncTask;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        js.delegate = this;
        new JSONfunctions().execute("http://192.168.6.43/employees.php");

        setContentView(R.layout.listplaceholder);
          ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();



        try {

                JSONArray  employees = retunfromAsyncTask.getJSONArray("Employees");

                for(int i=0;i<employees.length();i++){                      

                    JSONArray e = employees.getJSONArray(i);
                    HashMap<String, String> map = new HashMap<String, String>();    

                    map.put("name", "emp name:" + e.getString(0)+" "+e.getString(1)+" "+e.getString(2));
                    map.put("email id", "email id: " +  e.getString(3));
                    map.put("phone no", "phone no: " +  e.getString(4));

                    mylist.add(map);            
                }       
            }catch(JSONException e)        {
                 Log.e("log_tag", "Error parsing data "+e.toString());
            }

            ListAdapter adapter = new SimpleAdapter(this, mylist , R.layout.activity_main, 
                            new String[] { "name", "email id","phone no" }, 
                            new int[] { R.id.item_title, R.id.item_emailid ,R.id.item_phoneno});
           setListAdapter(adapter);

            final ListView lv = getListView();
            lv.setTextFilterEnabled(true);  
                }




    @Override
    public void processFinish(JSONObject result) {
        // TODO Auto-generated method stub
        retunfromAsyncTask=result;

    }

}


public class JSONfunctions extends AsyncTask<String, Void, JSONObject> {

    public Asynchtask delegate=null;

     InputStream is;
     String result ;
     JSONObject jArray;


    @Override
    protected JSONObject doInBackground(String... params) {
        // TODO Auto-generated method stub


        //http post
        try{
                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httppost = new HttpPost(params[0]);
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
                is = entity.getContent();

        }catch(Exception e){
                Log.e("log_tag", "Error in http connection "+e.toString());
        }
        try{
             BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
             StringBuilder sb = new StringBuilder();
             String line = null;
             while ((line = reader.readLine()) != null) {
                     sb.append(line + "
");
             }
             is.close();
             result=sb.toString();

     }catch(Exception e){
             Log.e("log_tag", "Error converting result "+e.toString());
     }

     try{

         jArray = new JSONObject(result);    

       //  MainActivity.dataFromAsyncTask=jArray;
     }catch(JSONException e){
             Log.e("log_tag", "Error parsing data "+e.toString());
     }

     return jArray;     
      //convert response to string

    }
    @Override
    protected void onPostExecute(JSONObject result) 
    {
          delegate.processFinish(result);

    }
}

manifest资源配置文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.dataread"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="4"
        android:targetSdkVersion="17" />
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.dataread.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
答案

要在Main Thread中获得结果,您将需要使用AsyncTask.get()方法,该方法使UI线程等待,直到doInBackground的执行未完成,但get()方法调用冻结主UI线程,直到doInBackground计算未完成。使用get()方法启动你的AsyncTask

String str_result=new 
             JSONfunctions().execute("http://192.168.6.43/employees.php").get();

在Thread中移动此行以避免冻结UI线程


Second and right way to utilize the use of AsyncTask move your code which you want to update with the result of doInBackground computation inside onPostExecute as :
public class JSONfunctions extends 
                  AsyncTask<String, Void, JSONObject> {

    public Asynchtask delegate=null;

     InputStream is;
     String result ;
     JSONObject jArray;


    @Override
    protected JSONObject doInBackground(String... params) {
      // your code here....
     return jArray;     
      //convert response to string

    }
    @Override
    protected void onPostExecute(JSONObject result) 
    {
          JSONArray  employees = 
                result.getJSONArray("Employees");
           // your code here...
      ListAdapter adapter = new SimpleAdapter(MainActivity.this, mylist , 
                                             R.layout.activity_main, 
                            new String[] { "name", "email id","phone no" }, 
                            new int[] { R.id.item_title, R.id.item_emailid 
                                      ,R.id.item_phoneno});
           MainActivity.this.setListAdapter(adapter);

            final ListView lv = MainActivity.this.getListView();
             //....
    }
}
另一答案
new JSONfunctions().execute("http://192.168.6.43/employees.php");

但我在哪里设置它的代表?

public Asynchtask delegate=null;

所以我认为你在这里获得NPE:

delegate.processFinish(result);

附:这一行js.delegate = this;与新的JSONfunctions实例无关。它为另一个实例设置委托(JSONfunctions js = new JSONfunctions();)

另一答案

使用get()我们可以从Async获得结果

response=new NetworkCallsHandler(this).execute(NetworkConstants.ASSETEVENTREPORT).get();

以上是关于如何将数据从AsyncTask返回到主线程的主要内容,如果未能解决你的问题,请参考以下文章

如何在切换片段时停止 AsyncTask?

在后台线程执行硬任务,在主线程返回结果

如何从片段返回主要活动

如何将数据从异步类传递到主活动类

如何从选项卡片段中的 AsyncTask Resftful WS 加载批量数据

Asynctask结果显示重新创建片段后