首页 > 解决方案 > 当我尝试重新加载活动时,尝试在空对象引用上调用虚拟方法 xx

问题描述

我有一个从 mySql db 加载一些数据以填充 Recyclerview 的活动。

PollActivity.java(相关代码)

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

    rv = findViewById(R.id.rv);

    // *** Rv Init ***
    LinearLayoutManager llm = new LinearLayoutManager(this);
    rv.setLayoutManager(llm);
    rv.setHasFixedSize(false);
    polls = new ArrayList<>();

    // SqLite data management
    db = new SQLiteHandler(getApplicationContext());
    HashMap<String, String> user = db.getUserDetails();
    final String userid = user.get("uid");
    // Local data
    String localBefore = Locale.getDefault().getLanguage().toUpperCase();
    final String local;
    switch (localBefore){

        case "IT":

            local = "IT";
            break;

        case "FR":

            local = "FR";
            break;

        case "DE":

            local = "DE";
            break;

        case "ES":

            local = "ES";
            break;

        default:

            local = "EN";
            break;

    }

    // ************
    // *** MAIN ***
    // ************

    // Tag used to cancel the request
    String tag_string_req = "req_login";

    MaterialDialog.Builder builder = new MaterialDialog.Builder(this)
            .title(R.string.strDialogProgressLoading_title)
            .content(R.string.strDialogProgressReg_desc)
            .progress(true, 0);
    final MaterialDialog myDialog = builder.build();
    myDialog.show();

    StringRequest strReq = new StringRequest(Request.Method.POST, AppConfig.POLL_LOADING, new Response.Listener<String>() {

        @Override
        public void onResponse(String response) {

            try {

                JSONObject jObj = new JSONObject(response);
                boolean error = jObj.getBoolean("error");

                if (!error) {

                    for(int i=0; i<jObj.length()-2; i++){

                        int j = i + 1;
                        JSONObject pollObject = jObj.getJSONObject("poll" + i);
                        JSONObject pollObjectNext = jObj.getJSONObject("poll" + j);
                        i++;

                        //Id to String Translate
                        int idInterests = getResources().getIdentifier("strInterestsItem" + pollObject.getString("id_interests"), "string", getPackageName());
                        String strInterests = getString(idInterests);

                        String strPoint;
                        if(pollObject.getString("sponsor").equals("UUABA")){

                            strPoint = "+200";

                        }else{

                            strPoint = "+150";

                        }

                        //String concatenation
                        String idPoll = "#" + pollObject.getString("id_poll");
                        String strQuestion = "#" + pollObject.getString("poll_question");
                        String IdUser = userid;


                        polls.add(new Poll(idPoll
                                , pollObject.getString("sponsor")
                                , pollObject.getString("poll_user_state")
                                , IdUser
                                , strInterests
                                , strQuestion
                                , pollObject.getString("poll_answer")
                                , pollObject.getString("id_poll_answer")
                                , pollObjectNext.getString("poll_answer")
                                , pollObjectNext.getString("id_poll_answer")
                                , strPoint));

                    }

                    initializeAdapter();
                    myDialog.dismiss();

                } else {

                    myDialog.dismiss();
                    // Error in loading. Get the error message
                    String errorMsg = jObj.getString("error_msg");
                    int idErrorRes = getResources().getIdentifier(errorMsg, "string", getPackageName());
                    String strErrorRes = getString(idErrorRes);

                    //POPUP ERRORE
                    new MaterialDialog.Builder(PollActivity.this)
                            .title(getResources().getString(R.string.strDialogAttention_title))
                            .titleColor(getResources().getColor(R.color.colorAccentDark))
                            .content(strErrorRes)
                            .positiveText(R.string.strDialogBtnPositive)
                            .contentGravity(GravityEnum.CENTER)
                            .positiveColor(getResources().getColor(R.color.colorAccent))
                            .icon(getResources().getDrawable(R.drawable.ic_dialog_alert))
                            .cancelable(false)
                            .autoDismiss(false)
                            .onPositive(new MaterialDialog.SingleButtonCallback() {
                                @Override
                                public void onClick(MaterialDialog dialog, DialogAction which) {
                                    dialog.dismiss();
                                }
                            })
                            .show();

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

        }
    }, new Response.ErrorListener() {

        @Override
        public void onErrorResponse(VolleyError error) {

            myDialog.dismiss();

            //POPUP ERRORE
            new MaterialDialog.Builder(PollActivity.this)
                    .title(getResources().getString(R.string.strDialogAttention_title))
                    .titleColor(getResources().getColor(R.color.colorAccentDark))
                    .content(getResources().getString(R.string.errorVolley1) + "(" + error + ")")
                    .positiveText(R.string.strDialogBtnPositive)
                    .contentGravity(GravityEnum.CENTER)
                    .positiveColor(getResources().getColor(R.color.colorAccent))
                    .icon(getResources().getDrawable(R.drawable.ic_dialog_alert))
                    .cancelable(false)
                    .autoDismiss(false)
                    .onPositive(new MaterialDialog.SingleButtonCallback() {
                        @Override
                        public void onClick(MaterialDialog dialog, DialogAction which) {
                            dialog.dismiss();
                        }
                    })
                    .show();

        }
    }) {

        @Override
        protected Map<String, String> getParams() {
            // Posting parameters to loading url
            Map<String, String> params = new HashMap<String, String>();
            params.put("userid", userid);
            params.put("local", local);

            //Log.d("NINJA", "UserID: " + userid);
            //Log.d("NINJA", "Local: " + local);
            return params;

        }

    };

    // Adding request to request queue
    AppVolleyController.getInstance().addToRequestQueue(strReq, tag_string_req);

    // ************
    // ************
    // ************


private void initializeAdapter(){

    RVAdapter adapter = new RVAdapter(polls);
    rv.setAdapter(adapter);

}

public void reloadActivity(){

    startActivity(getIntent());
    finish();

}

}

RVAdapter.java(我的 Recycler View Adapter)

public class RVAdapter extends RecyclerView.Adapter<RVAdapter.PollViewHolder> {

public static class PollViewHolder extends RecyclerView.ViewHolder {

    CardView cv;
    TextView txtIdPoll;
    ImageView imgSponsor;
    ImageView imgNew;
    TextView txtIdInterests;
    TextView txtQuestion;
    RadioGroup radioGroupAnswers;
    RadioButton radioAnswer1;
    RadioButton radioAnswer2;
    Button btnPoint;

    PollViewHolder(View itemView) {

        super(itemView);

        cv = itemView.findViewById(R.id.cv);
        txtIdPoll = itemView.findViewById(R.id.txtIdPoll);
        imgSponsor = itemView.findViewById(R.id.imgSponsor);
        imgNew = itemView.findViewById(R.id.imgNew);
        txtIdInterests = itemView.findViewById(R.id.txtIdInterests);
        txtQuestion = itemView.findViewById(R.id.txtQuestion);
        radioGroupAnswers = itemView.findViewById(R.id.radioGroupAnswers);
        radioAnswer1 = itemView.findViewById(R.id.radioAnswer1);
        radioAnswer2 = itemView.findViewById(R.id.radioAnswer2);
        btnPoint = itemView.findViewById(R.id.btnPoint);

    }
}

List<Poll> polls;
//Context context;

public RVAdapter(List<Poll> polls){

    this.polls = polls;
    //this.context = context;

}

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {

    super.onAttachedToRecyclerView(recyclerView);

}

@Override
public PollViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.poll_item, viewGroup, false);
    PollViewHolder pvh = new PollViewHolder(v);
    return pvh;

}

@Override
public void onBindViewHolder(final PollViewHolder pollViewHolder, final int i) {

    final int rb1id = 1000;
    final int rb2id = 2000;

    //Setting RadioButton ID
    pollViewHolder.radioAnswer1.setId(rb1id);
    pollViewHolder.radioAnswer2.setId(rb2id);

    pollViewHolder.txtIdPoll.setText(polls.get(i).txtIdPoll);

    if(polls.get(i).txtSponsor.equals("UUABA")){

        pollViewHolder.imgSponsor.setImageResource(R.drawable.ic_logo_red_bg);

    }else{

        pollViewHolder.imgSponsor.setImageResource(R.drawable.ic_sponsor_green_bg);

    }

    if(polls.get(i).txtNew.equals("0")){

        pollViewHolder.imgNew.setImageResource(R.drawable.ic_new);

    }else{

        pollViewHolder.btnPoint.setEnabled(false);
        pollViewHolder.btnPoint.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.SRC_ATOP);

    }

    pollViewHolder.txtIdInterests.setText(polls.get(i).txtIdInterests);
    pollViewHolder.txtQuestion.setText(polls.get(i).txtQuestion);
    pollViewHolder.radioAnswer1.setText(polls.get(i).txtAnswer1);
    pollViewHolder.radioAnswer2.setText(polls.get(i).txtAnswer2);
    pollViewHolder.btnPoint.setText(polls.get(i).txtPoint);

    pollViewHolder.btnPoint.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if(pollViewHolder.radioGroupAnswers.getCheckedRadioButtonId() == -1){

                Snackbar snackbar = Snackbar.make(v, R.string.strSnackPoll, Snackbar.LENGTH_LONG);
                View snackbarView = snackbar.getView();
                TextView textView =snackbarView.findViewById(android.support.design.R.id.snackbar_text);
                textView.setTextColor(Color.YELLOW);
                snackbar.show();

            }else{

                QueryUtils queryUtils = new QueryUtils();
                String IdPoll = String.valueOf((polls.get(i).txtIdPoll)).replace("#", "");

                switch (pollViewHolder.radioGroupAnswers.getCheckedRadioButtonId()){

                    case 1000:

                        queryUtils.upgPollAnswer(String.valueOf((polls.get(i).txtUserId)), IdPoll, String.valueOf((polls.get(i).txtIdAnswer1)));
                        break;

                    case 2000:

                        queryUtils.upgPollAnswer(String.valueOf((polls.get(i).txtUserId)), IdPoll, String.valueOf((polls.get(i).txtIdAnswer2)));
                        break;

                }

            }

        }
    });

}

@Override
public int getItemCount() {

    return polls.size();

}

}

此时,我想在按钮单击时更新 db 字段并重新加载 PollActivity.java 以强制 RecyclerView 更新(我希望 NEW 图像从更新的 CardView 中消失)。我想这样做是调用我的 QueryUtils.java 的方法(它将包含的方法之一),避免在适配器内编写过多的代码。

QueryUtils.java

@SuppressLint("Registered")
public class QueryUtils extends Application {

private String tag_string_req = "req_poll_answer_upg";

public void upgPollAnswer(final String UserId, final String PollId, final String AnswerId){

    Log.d("NINJA", "Utente: " + UserId);
    Log.d("NINJA", "Poll: " + PollId);
    Log.d("NINJA", "Risposta: " + AnswerId);

    StringRequest strReq = new StringRequest(Request.Method.POST, AppConfig.POLL_ANSWER_UPG, new Response.Listener<String>() {

        @Override
        public void onResponse(String response) {

            try {

                JSONObject jObj = new JSONObject(response);
                boolean error = jObj.getBoolean("error");
                String message = jObj.getString("message");

                if (!error) {

                    Log.d("NINJA", "Messaggio: " + message);
                    PollActivity pollActivity = new PollActivity();
                    pollActivity.reloadActivity();

                } else {

                    //myDialog.dismiss();

                    // Error in login. Get the error message
                    String errorMsg = jObj.getString("error_msg");
                    int idErrorRes = getResources().getIdentifier(errorMsg, "string", getPackageName());
                    String strErrorRes = getString(idErrorRes);


                    Log.d("NINJA", "ErrorePhP: " + strErrorRes);
                    //POPUP ERRORE
                    /*new MaterialDialog.Builder(QueryUtils.this)
                            .title(getResources().getString(R.string.strDialogAttention_title))
                            .titleColor(getResources().getColor(R.color.colorAccentDark))
                            .content(strErrorRes)
                            .positiveText(R.string.strDialogBtnPositive)
                            .contentGravity(GravityEnum.CENTER)
                            .positiveColor(getResources().getColor(R.color.colorAccent))
                            .icon(getResources().getDrawable(R.drawable.ic_dialog_alert))
                            .cancelable(false)
                            .autoDismiss(false)
                            .onPositive(new MaterialDialog.SingleButtonCallback() {
                                @Override
                                public void onClick(MaterialDialog dialog, DialogAction which) {
                                    dialog.dismiss();
                                }
                            })
                            .show();*/

                }

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

        }
    }, new Response.ErrorListener() {

        @Override
        public void onErrorResponse(VolleyError error) {


            Log.d("NINJA", "ErroreVolley: " + error);
            //myDialog.dismiss();

            //POPUP ERRORE
            /*new MaterialDialog.Builder(QueryUtils.this)
                    .title(getResources().getString(R.string.strDialogAttention_title))
                    .titleColor(getResources().getColor(R.color.colorAccentDark))
                    .content(getResources().getString(R.string.errorVolley1) + "(" + error + ")")
                    .positiveText(R.string.strDialogBtnPositive)
                    .contentGravity(GravityEnum.CENTER)
                    .positiveColor(getResources().getColor(R.color.colorAccent))
                    .icon(getResources().getDrawable(R.drawable.ic_dialog_alert))
                    .cancelable(false)
                    .autoDismiss(false)
                    .onPositive(new MaterialDialog.SingleButtonCallback() {
                        @Override
                        public void onClick(MaterialDialog dialog, DialogAction which) {
                            dialog.dismiss();
                        }
                    })
                    .show();*/

        }
    }) {

        @Override
        protected Map<String, String> getParams() {
            // Posting parameters to loading url
            Map<String, String> params = new HashMap<String, String>();
            params.put("userid", UserId);
            params.put("id_poll", PollId);
            params.put("id_answer", AnswerId);

            return params;

        }

    };

    // Adding request to request queue
    AppVolleyController.getInstance().addToRequestQueue(strReq, tag_string_req);

}

}

在更新过程结束时,我调用 PollActivity 中的 reloadActivity 方法来重新加载自身。此调用生成以下错误:

LOGCAT

java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread android.app.ActivityThread.getApplicationThread()' on a null object reference
    at android.app.Activity.startActivityForResult(Activity.java:4226)
    at android.support.v4.app.BaseFragmentActivityApi16.startActivityForResult(BaseFragmentActivityApi16.java:54)
    at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:68)
    at android.app.Activity.startActivityForResult(Activity.java:4183)
    at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:751)
    at android.app.Activity.startActivity(Activity.java:4522)
    at android.app.Activity.startActivity(Activity.java:4490)
    at com.uuaba.uuaba.core.PollActivity.reloadActivity(PollActivity.java:345)
    at com.uuaba.uuaba.utils.QueryUtils$1.onResponse(QueryUtils.java:48)
    at com.uuaba.uuaba.utils.QueryUtils$1.onResponse(QueryUtils.java:33)
    at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:60)
    at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:30)
    at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6119)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

我是 Android 编程新手,我尝试了在这个很棒的论坛中找到的不同解决方案,但没有一个对我有用。

请帮我

标签: androidmethodsnullpointerexceptionandroid-recyclerview

解决方案


Problem is that you are trying to create a new instance of activity without the use of intent :

PollActivity pollActivity = new PollActivity();
pollActivity.reloadActivity();

You should replace this code with the following lines:

public void onClickChangeActivity() {
    Intent intent = new Intent(this, PollActivity.class);
    startActivity(intent);
}

But your solution is far away from the ideal solutions available in the market. Restarting the activity whenever there is a change in data because you have to update data can never be a good way to go. Try considering one of these ways to prevent activity restart

  1. Create a data stream(list of data) and keep on reading that on activity level.
  2. Create a local broadcast receiver

    Do let me know if you need help in above ways.

As a quick fix for the problem you can use this hackish way

  1. Create a callback

    interface Result { void success(ResponseModel model); void failure(Throwable throw); }

  2. In QueryUtils

List resultCallbacks = new ArrayList(); public void addCallback(Result result) { resultCallbacks.add(result); }

create List resultCallbacks and a method addCallback to add the callbacks

  1. In PollsActivity write this

((QueryApplication)getApplicationContext().getApplication()).addCallbacks(this);

and implement the callback.

On receiving any data update your list and do

RVUpdater.notifyDataSetChanged();

Hope this will help.


推荐阅读