Okhttp3在请求加载之前关闭活动时使应用程序崩溃

时间:2017-12-11 10:21:00

标签: java android crash okhttp3 android-runonuithread

一切正常。但我正在加载问题片段并立即单击返回并退出应用程序而不让请求完成。它崩溃了应用程序。我试着环顾四周,但找不到能帮我防止崩溃的修复方法。我正在附加logcatQuestions类供参考。

logcat的

12-11 15:37:44.898 16772-16835/com.aftertutor.app E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
                                                                    Process: com.aftertutor.app, PID: 16772
                                                                    java.lang.NullPointerException
                                                                        at com.aftertutor.app.Question$1.onResponse(Question.java:112)
                                                                        at okhttp3.RealCall$AsyncCall.execute(RealCall.java:153)
                                                                        at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
                                                                        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:841)

问题类

package com.aftertutor.app;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.aftertutor.app.model.API;
import com.dpizarro.autolabel.library.AutoLabelUI;
import com.dpizarro.autolabel.library.AutoLabelUISettings;
import com.github.thunder413.datetimeutils.DateTimeStyle;
import com.github.thunder413.datetimeutils.DateTimeUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.Date;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;


public class Question extends Fragment {

    public String id;
    public TextView title;
    public TextView desc;
    public TextView date;
    public TextView edit;
    public TextView report;
    public TextView username;
    public AutoLabelUI tags;
    public CardView cardView;
    public ProgressBar progressBar;
    public TextView votes;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_question, null);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        // Equivalent to on Create
        super.onViewCreated(view, savedInstanceState);

        getActivity().setTitle("Loading...");

        title = view.findViewById(R.id.ques_title);
        desc = view.findViewById(R.id.ques_desc);
        date = view.findViewById(R.id.ques_time);
        edit = view.findViewById(R.id.ques_edit);
        report = view.findViewById(R.id.ques_report);
        username = view.findViewById(R.id.ques_username);
        tags = view.findViewById(R.id.ques_labels);
        cardView = view.findViewById(R.id.ques_card);
        progressBar = view.findViewById(R.id.ques_progress);
        votes = view.findViewById(R.id.ques_votes);

        Bundle arg = getArguments();
        if (arg != null && arg.containsKey("id")) {
            id = arg.getString("id");
        }

        loadQuestion(id);

    }

    public void loadQuestion(String qid) {
        final API api = new API();
        OkHttpClient client = new OkHttpClient();

        RequestBody body = new FormBody.Builder()
                .add("qid", qid)
                .build();

        Request request = api.call("get_question", body, getContext(), getActivity());

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                call.cancel();
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        MaterialDialog dialog = api.prepareDialog(getContext(), "An Error Occoured", "An Error Occoured. Please make sure you are connected to the internet and try again. If the issue still persists please contact support.");
                        dialog.show();
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                final String responseText = response.body().string();
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        try {

                            JSONObject jsonObject = new JSONObject(responseText);

                            if (jsonObject.get("status").equals("ok"))
                            {
                                JSONObject payload = jsonObject.getJSONObject("payload");
                                JSONObject questionItem = payload.getJSONObject("question");

                                title.setText(questionItem.get("title").toString());
                                getActivity().setTitle(questionItem.get("title").toString());
                                desc.setText(questionItem.get("description").toString());
                                date.setText(DateTimeUtils.getTimeAgo(getContext(), new Date(questionItem.getInt("postedOn") * 1000L), DateTimeStyle.AGO_FULL_STRING));
                                votes.setText(questionItem.getInt("votes") + "");
                                username.setText("@" + questionItem.get("postedBy").toString());
                                String[] taggs = api.toStringArray(questionItem.getJSONArray("tags"));

                                edit.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        // Edit Page here
                                    }
                                });

                                report.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        MaterialDialog dialog = new MaterialDialog.Builder(getContext())
                                                .title("Report this question because...")
                                                .items(R.array.report_array)
                                                .itemsCallbackSingleChoice(0, new MaterialDialog.ListCallbackSingleChoice() {
                                                    @Override
                                                    public boolean onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
                                                        Toast.makeText(getContext(), "YOU SELECTED: " + which, Toast.LENGTH_SHORT).show();
                                                        return false;
                                                    }
                                                })
                                                .content("Reporting will let us know that something isn't wrong with this post. We will take action asap.")
                                                .positiveText("Report")
                                                .onPositive(new MaterialDialog.SingleButtonCallback() {
                                                    @Override
                                                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                                                        Toast.makeText(getContext(), "Reported", Toast.LENGTH_SHORT).show();
                                                    }
                                                })
                                                .negativeText("Cancel")
                                                .build();
                                        dialog.show();
                                    }
                                });

                                AutoLabelUISettings autoLabelUISettings = new AutoLabelUISettings.Builder()
                                        .withMaxLabels(5)
                                        .withShowCross(false)
                                        .withLabelsClickables(false)
                                        .withBackgroundResource(R.drawable.rounded_corner)
                                        .withTextSize(R.dimen.custom_label_font_size)
                                        .withLabelPadding(R.dimen.custom_label_font_padding)
                                        .build();
                                tags.setSettings(autoLabelUISettings);
                                tags.clear();

                                for (String tag: taggs) {
                                    tags.addLabel(tag);
                                }
                                progressBar.setVisibility(View.GONE);
                                cardView.setVisibility(View.VISIBLE);

                            }
                            else if (jsonObject.get("status").equals("error"))
                            {
                                MaterialDialog dialog = api.prepareDialog(getContext(), jsonObject.getJSONObject("dialog").get("title").toString(), jsonObject.getJSONObject("dialog").get("message").toString());
                                dialog.show();
                            }
                            else
                            {
                                MaterialDialog dialog = api.prepareDialog(getContext(), "An Error Occurred", "An Error Occurred. Please make sure you are connected to the internet and try again. If the issue still persists please contact support.");
                                dialog.show();
                            }

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

            }
        });

    }

}

2 个答案:

答案 0 :(得分:1)

您必须取消onPause()中的来电,因此请拨打电话:

private Call call;

然后将您的loadQuestion()方法更改为:

call = client.newCall(request);
call.enqueue(new Callback() {

取消请求:

@Override
public void onPause() {
    super.onPause();
    if (call != null){
        call.cancel();
    }
}

答案 1 :(得分:0)

由于您确定如果Exception暂停,请求的响应会导致应用(Fragment)崩溃,那么您可以在类中声明boolean,如:

private boolean active= true;

然后在onResume

@Override
public void onResume() {
  super.onResume();
  active= true;

}

然后在onPause

@Override
public void onPause() {
  super.onPause();
  active= false;

}

然后在你片段的电话onResponse中添加if声明:

@Override
public void onResponse(Call call, Response response) throws IOException {
    if(active){
     //Call your extra code here!
   }
}