为什么我的AsyncTask在主线程上运行?

时间:2015-06-02 15:27:32

标签: java android multithreading android-fragments android-asynctask

我在容器活动中有一个标签片段。

我想下载一些数据以显示在标签中。在选项卡中,我创建了一个asynctask,我在onCreateView中膨胀片段布局后执行。当我这样做时,AsyncTask的doInBackground ...工作发生在主线程上,并且视图在完成之前不会加载。我的所有进度......日志在任务完成后立即显示。

但是,如果我在片段布局中放置一个按钮并启动asynctask工作作为对按钮单击的响应,它按预期工作,我得到我正常间隔的进度更新。

那么,为什么AsyncTask在主线程上运行,如果它是我的片段启动时发生的第一件事?而且,我该如何防止这种情况?我的最终目标是在下载数据时显示进度轮。

编辑。这是我称之为AsyncTask的地方。

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

    final View rootView = inflater.inflate(R.layout.temp_my_moments, container, false);

    getMyClips(getActivity(), rootView, p_session, p_person,progressBar);

//If I use this button, it works fine:
//    test = (Button) rootView.findViewById(R.id.testbutton);
//    test.setOnClickListener(new View.OnClickListener() {
//        @Override
//        public void onClick(View v) {
 //           progressBar =(ProgressBar) rootView.findViewById(R.id.myMomentsProgress);
  //          getMyClips(getActivity(), rootView, p_session, p_person, progressBar);
  //      }
 //   });
    return rootView;
}

这是getMyClips():

public void getMyClips(Context context,View view,String thisSession,String thisPerson,ProgressBar progressBar) {
    Log.d("Currently running", "getMyClips");
        JSONObject params = new JSONObject();
        try {
            params.put("Function", clipsMine_apiCall);
            params.put("p_session", thisSession);
            params.put("p_person", thisPerson);
        } catch (JSONException e1) {
            e1.printStackTrace();
        }

        ApiClipCaller webServiceTask = new ApiClipCaller(context,view,progressBar);
        if (webServiceTask.hasConnection()) {
            webServiceTask.execute(params);
        } else {
                //TODO no internet connection
        }
}

编辑这是我的AsyncTask。这是在片段中:

public class ApiClipCaller extends AsyncTask<JSONObject, Integer, ApiResponse> {
public Context context;
public String clipID;
public String sessionID;
public String personID;
public String functionName;
public View view;
public ProgressBar progressBar;
public final String apiURL = "....";  //need to keep private
LinearLayout loading;

public ApiClipCaller(Context c, View v,ProgressBar progressBar) {
this.context = c;
this.view = v;
this.progressBar = progressBar;
loading = (LinearLayout) view.findViewById(R.id.loadingMyMoments);
}

    @Override 
    protected ApiResponse doInBackground(JSONObject... params) {
        JSONObject realParams = params[0];
        try {
            functionName = realParams.getString("Function");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        ApiResponse responseObject = masterFunction(realParams);

        //making some work to see if it is running correctly
        for (int i=10;i<=100;i += 10)
        {
            try {
                Thread.sleep(1000);
                publishProgress(i);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        return responseObject;
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        loading.setVisibility(View.VISIBLE);
        progressBar.setProgress(progress[0]);
        Log.d("progress",Integer.toString(progress[0]));
    }

    @Override
    protected void onPostExecute(ApiResponse responseObject) {
        loading.setVisibility(View.GONE);
        if (functionName.equals(clipsMine_apiCall)) {
            JSONObject clipObject = responseObject.getResponseJSONObject();

           //just testing here to see if I can get data back in the fragment view when it is done. 
///This works as expected.
  String responseString = responseObject.getResponseString();
             TextView showAsyncResults = (TextView) view.findViewById(R.id.testAsyncTask);
             showAsyncResults.setText(responseString);
        }
        super.onPostExecute(responseObject);
    }
}

1 个答案:

答案 0 :(得分:0)

所以,似乎答案就是我说这一切都错了。当第一个活动或片段加载时,无法启动asynctask,因为onCreate等方法实际上不在UI线程上。因此,正如Ordous指出的那样,AsyncTask不能直接从那里执行。

相反,似乎解决方案是在应用程序首次启动时通过创建扩展Application并从那里执行加载工作的类来加载信息,因为这必然位于主线程上。可以从活动中调用方法来访问布局并创建进度条或类似方法。

参考:http://developer.android.com/reference/android/app/Application.html 一个很好的例子:http://www.intertech.com/Blog/androids-application-class/