【问题标题】:OnCreate ends before data can be retrieved asynchronouslyOnCreate 在可以异步检索数据之前结束
【发布时间】:2017-08-03 21:06:36
【问题描述】:

我正在编写一些代码,这些代码将从 Facebook 提取 JSON 信息并将其放置在 EditText 视图中。我遇到的问题是,由于我调用来检索数据的函数是一个异步函数,因此在我的活动的 onCreate 函数结束后检索数据,因此文本无法更新,因为当时它为空. 如何确保在检索数据之前我的 OnCreate 方法不会结束?

这是我的活动课程:

public class PersonalInfoMain extends AppCompatActivity implements GraphService.OnDownloadComplete {

    public EditText mName;
    public String name;

    String mValue, mField;

    private static final String TAG = "PersonalInfoMain";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate: starts");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_personal_info_main);

        mName = (EditText) findViewById(R.id.editText_name);

        //Calling GraphService class
        GraphService mGraphService = new GraphService(this);
        mField = "name";
        mGraphService.execute(mField);
        mName.setText(name);
    }
}

    //My Callback function located in the same activity:
    @Override
    public void onDownloadComplete(String s) {
            name = s;
    }

这是我标记为 GraphService 以从 Facebook 提取信息的课程:

public class GraphService extends AsyncTask<String, Void, String>{

private static final String TAG = "GraphService";

private String mField;
private String mValue;

private final OnDownloadComplete mCallback;

public interface OnDownloadComplete{
    void onDownloadComplete(String data);
}

public GraphService(OnDownloadComplete callback){
    mCallback = callback;
}

@Override
public String doInBackground(final String... params) {
    Log.d(TAG, "doInBackground: starts");

    mField = params[0];

    //Beginning of Facebook implementation
    GraphRequest request = GraphRequest.newMeRequest(
        AccessToken.getCurrentAccessToken(),
        new GraphRequest.GraphJSONObjectCallback() {

            @Override
            public void onCompleted(JSONObject object, GraphResponse response) {
                try {
                        mValue = object.getString(mField);

                } catch (JSONException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    );

    Bundle parameters = new Bundle();
    parameters.putString("fields", mField);
    request.setParameters(parameters);
    request.executeAsync();
    return mValue;

}

@Override
protected void onPostExecute(String s) {
    if(mCallback != null){
        mCallback.onDownloadComplete(s);
    }
}

我的 Android 监视器显示此工作流程:

D/MainActivity: onCreate: starts
D/MainActivity: isLoggedIn: starts
D/MainActivity: isLoggedIn: ends
D/MainActivity: onCreate: ends
D/PersonalInfoMain: onCreate: starts
D/PersonalInfoMain: onCreate: name = null
D/GraphService: doInBackground: starts
D/PersonalInfoMain: onCreate: ends
D/PersonalInfoMain: onResume: starts
D/PersonalInfoMain: onResume: name = null
D/GraphService: doInBackground: ends
D/PersonalInfoMain: onResume: ends
D/GraphService: onPostExecute: starts
D/PersonalInfoMain: onDownloadComplete: starts
D/PersonalInfoMain: onDownloadComplete: ends
D/GraphService: onPostExecute: ends
D/GraphService: onCompleted: starts, JSON object = {"name":"Tom"}, response = {"name":"Tom"}
D/GraphService: onCompleted: json object:{"name":"Tom"}
D/GraphService: onCompleted: ends

如您所见,我的活动中的 .setText() 方法将其设置为空值,因为异步任务(onCompleted() 方法)尚未返回数据。 如何确保在检索数据之前我的 OnCreate 方法不会结束?

如果有任何建议,我将不胜感激。

谢谢。

【问题讨论】:

    标签: android facebook android-asynctask oncreate


    【解决方案1】:

    你不能也你不应该因为你正在做异步网络请求。一旦你从网络调用中获得了所需的数据,你最好只调用 setText 方法。

    //我的回调函数位于同一个activity中:

    @Override
    public void onDownloadComplete(String s) {
            mName.setText(s);
    }
    

    【讨论】:

    • 嗨 Sunil,我一直听说像网络请求这样的短动作应该异步调用。你能解释一下为什么我不应该这样做吗?我已经试过你的代码,它仍然没有更新 mName,因为在 onDownloadComplete 函数结束后正在调用 JSON 检索代码,(如您在 Logcat 中看到的)
    • 是的,我刚刚发现您再次在 doInBackground 中进行异步 GraphRequest,因此在这种情况下,您甚至在从请求中获得结果之前就调用了 return。这里不需要AsyncTask,直接调用GraphRequest即可。
    【解决方案2】:

    也许您可以尝试将代码从 onDownloadComplete() 移至 onPostExecute()。我个人认为没有必要使用

    公共接口 OnDownloadComplete{

    void onDownloadComplete(String data);
    

    }

    这里。

    doInBackground()方法执行后,其结果(mValue)会作为s传递给onPostExecute(String s)。

    在 onPostExecute() 中,您可以更新您的 UI。

    这是我在这里的第一个答案。如果有什么问题,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-12
      • 2021-09-14
      • 1970-01-01
      • 2017-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-08
      相关资源
      最近更新 更多