【问题标题】:Android SetText in OkHttp Async callback causing crashOkHttp异步回调中的Android SetText导致崩溃
【发布时间】:2016-04-14 16:54:19
【问题描述】:

我有一个 android 活动,它在加载活动时执行异步 Okhttp 调用(从 onStart 方法作为 getActiveRequests() 调用)。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

Button btLogout;
UserLocalStore userLocalStore;
String username;
String userEmail;
String recentAppName;
String recentRequestTime;
String isExpired;
TelephonyManager telephonyManager;
OkHttpClient client;
TextView tvRecentAppName, tvRecentRequestTime, tvIsExpired;


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

    userLocalStore = new UserLocalStore(this);
    telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

    TextView tvUserName = (TextView) findViewById(R.id.userName);
    TextView tvUserEmail = (TextView) findViewById(R.id.userEmail);

    tvRecentAppName = (TextView) findViewById(R.id.recentAppName);
    tvRecentRequestTime = (TextView) findViewById(R.id.recentRequestTime);
    tvIsExpired = (TextView) findViewById(R.id.isExpired);

    client = new OkHttpClient();
    username = userLocalStore.getLoggedInUser().name;
    userEmail = userLocalStore.getLoggedInUser().email;

    tvUserEmail.setText(userEmail);
    tvUserName.setText(username);

    btLogout = (Button) findViewById(R.id.btLogout);
    btLogout.setOnClickListener(this);
}

@Override
protected void onStart() {
    super.onStart();

    if(authenticateUser() == true){
        getActiveRequests();
    }else{
        startActivity(new Intent(this, LoginActivity.class));
    }
}

我想要做的是在使用 SetText 方法进行 Http 调用后更新 UI。这是我的调用,在 GetActiveRequests() 方法中实现。

client.newCall(request)
            .enqueue(new Callback() {

                @Override
                public void onFailure(Call call, IOException e) {
                    String hello = "failed call";
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    final String responseData = response.body().string();

                    if (responseData != null) {
                        Gson gson = new Gson();
                        JsonElement element = gson.fromJson(responseData, JsonElement.class);
                        JsonObject jsonObject = element.getAsJsonObject();
                        final AccessRequest request = gson.fromJson(jsonObject, AccessRequest.class);

                        recentAppName = request.AppName.toString();
                        recentRequestTime = request.RequestTime.toString();
                        if (request.IsExpired)
                            isExpired = "Has Expired";
                        else isExpired = "Active";

                        tvRecentAppName.setText(recentAppName);
                        tvRecentRequestTime.setText(recentRequestTime);
                        tvIsExpired.setText(isExpired);
                    }
                }
            });

我遇到的问题是,当调试器到达SetText 代码行时,它会导致应用程序崩溃并关闭。我不知道如何解决这个问题,但我认为这与 Okhttp Async 调用无法更新 UI 有关,因为我的 setText 方法在 onCreate() 中运行良好。

【问题讨论】:

标签: java android android-asynctask settext


【解决方案1】:

那是因为视图的更新只能在 UI 线程上完成,而 OkHttp 的 onResponse 在后台线程上运行。尝试像这样在主线程上运行它:

@Override
public void onResponse(Call call, Response response) throws IOException {
     final String responseData = response.body().string();

     if (responseData != null) {
        Gson gson = new Gson();
        JsonElement element = gson.fromJson(responseData, JsonElement.class);
        JsonObject jsonObject = element.getAsJsonObject();
        final AccessRequest request = gson.fromJson(jsonObject, AccessRequest.class);

        recentAppName = request.AppName.toString();
        recentRequestTime = request.RequestTime.toString();
        if (request.IsExpired)
            isExpired = "Has Expired";
        else isExpired = "Active";

        MainActivity.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
               //Handle UI here                        
               tvRecentAppName.setText(recentAppName);
               tvRecentRequestTime.setText(recentRequestTime);
               tvIsExpired.setText(isExpired);                
            }
       });
    }
}

同样,如果您在 onFailure 上更新了任何视图,请在 UI 线程上进行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-13
    • 1970-01-01
    • 1970-01-01
    • 2016-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多