访问片段的子视图时出现空指针异常

Posted

技术标签:

【中文标题】访问片段的子视图时出现空指针异常【英文标题】:nullpointer exception while accessing childviews of a fragment 【发布时间】:2018-06-06 13:08:59 【问题描述】:

我正在创建一个包含三个标签片段的活动。我想将来自对象(在父活动中可用)的数据设置为片段的子视图。我尝试通过片段的公共方法来做到这一点。但是当尝试访问视图时,它返回空指针异常并且应用程序崩溃。有人可以帮我解决这个问题吗?

父活动是:

public class EnquiryViewActivity extends AppCompatActivity implements IFragmentToActivity 

    private Context mContext;
    // Session Manager Class
    SessionManagement session;
    private RequestQueue requestQueue;
    private Gson gson;

    //String enquiryId;
    int enId, uid;
    Enquiry enquiry;

    // Alert Dialog Manager
    AlertDialogManager alert = new AlertDialogManager();

    /* Button btn_MoreEnqDetails, btn_ToSiteVisit, btn_nextEnq2;
     EditText etName, etAddress, etSiteAddress, etPhoneNo, etMob, etEmail;

     private RadioGroup rgrp_familyType;
     private RadioButton radioselectedFamilyType;
 */
    private TabLayout addenqtabLayout;
    private ViewPager addenqviewPager;

    //Fragments
    ContactFragment contactFragment;
    RequirementsFragment requirementsFragment;
    FollowUpFragment followupFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_enquiry);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        //--------------------------------------------

        //Initializing viewPager
        addenqviewPager = (ViewPager) findViewById(R.id.addenqviewpager);
        addenqviewPager.setOffscreenPageLimit(3);

        //Initializing the tablayout
        addenqtabLayout = (TabLayout) findViewById(R.id.addenqtablayout);
        addenqtabLayout.setupWithViewPager(addenqviewPager);

        addenqviewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() 
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) 
            

            @Override
            public void onPageSelected(int position) 
                addenqviewPager.setCurrentItem(position, false);
            

            @Override
            public void onPageScrollStateChanged(int state) 
            
        );

        setupViewPager(addenqviewPager);

        //----------------------------------------------

        enquiry = new Enquiry();
        try 

            mContext = this;
            enId = getIntent().getIntExtra("EnquiryId", -1);
            uid = getIntent().getIntExtra("UserId", -1);
            if (enId != -1) 
                Log.d("h", "get enqid is " + enId);
                enquiry = EnquiryORM.findEnquiryById(mContext, enId);
             else 
                Log.d("h", "didn't get bid");
            

            /*int position = tabLayout.getSelectedTabPosition();
            Fragment fragment = adapter.getFragment(tabLayout
                    .getSelectedTabPosition());
            if (fragment != null) 
                switch (position) 
                    case 0:
                        ((TabFragment1) fragment).onRefresh();
                        break;
                    case 1:
                        ((TabFragment2) fragment).onRefresh();
                        break;
                
            */
            contactFragment.setDataToScreen(enquiry);
            contactFragment.disableAllViews();

         catch (NumberFormatException e) 

            Log.d("NumberFormatException: ", "some int is null");
            Log.d("NumberFormatException: ", e.getMessage());
        

    

    //---------------------------------------------------------------

    @Override
    public void showToast(String msg) 
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    

    @Override
    public void communicateToFragment2() 
        /*RequirementsFragment fragment = (RequirementsFragment) adapter.getFragment(1);
        if (fragment != null) 
            fragment.fragmentCommunication();
         else 
            Log.i("log", "Fragment 2 is not initialized");
        */
    


    @Override
    public void gotoMoreDetails() 

        if (ConnectivityReceiver.isConnected()) 
            //fetch and
            //send indent to next activity to view more details
            //show option to edit details
            fetchMoreEnquiryDetails();

         else 
            alert.showAlertDialog(EnquiryViewActivity.this, "Network Error", "Internet is not available!\nCannot connect to server", false);
        
    

    @Override
    public void gotoSiteVisit() 

        Intent in = new Intent(EnquiryViewActivity.this, SiteVisitViewActivity.class);
        in.putExtra("EnquiryId", enId);
        in.putExtra("UserId", uid);
        startActivity(in);
    

    @Override
    public void saveDataContacts(Enquiry enq) 

        if (enquiry != null) 
            enq.setId(enquiry.getId());
            enq.setStatus(enquiry.getStatus());
            enq.setUser_id(enquiry.getUser_id());
            enq.setEnqstatusnew(enquiry.getEnqstatusnew());
            enq.setCreateddate(getDateTime());
        

        int enI=(int)EnquiryORM.insertEnquiry(mContext, enq);
        enq.setId(enI);
    

    //-----------------------------------------------------------------------

    private void setupViewPager(ViewPager viewPager) 
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        contactFragment = new ContactFragment();
        requirementsFragment = new RequirementsFragment();
        followupFragment = new FollowUpFragment();
        adapter.addFragment(contactFragment, "CONTACT DETAILS");
        adapter.addFragment(requirementsFragment, "REQUIREMENTS");
        adapter.addFragment(followupFragment, "FOLLOW-UP");
        viewPager.setAdapter(adapter);
    

    private void fetchMoreEnquiryDetails() 
        // Get a RequestQueue
        // RequestQueue requestQueue = MyVolleySingleton.getInstance(this.getApplicationContext()).getRequestQueue();
        requestQueue = Volley.newRequestQueue(this);

        //create gson instance which is used to parse json
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.excludeFieldsWithoutExposeAnnotation();
        //gsonBuilder.setDateFormat("M/d/yy hh:mm a");
        gson = gsonBuilder.create();

        StringRequest sr = new StringRequest(Request.Method.POST, EndPoints.GET_SELECTED_ENQUIRIES_URL, new Response.Listener<String>() 
            @Override
            public void onResponse(String response) 

                Log.d("d", "getting response.........\n" + response);
                Toast.makeText(getApplicationContext(), "Selected Enquiry JSON data :" + response, Toast.LENGTH_LONG).show();

                //Enquiry detailEnquiry = gson.fromJson(response, Enquiry.class);
                //detailEnquiry.setUser_id(uid);
                Enquiry detailEnquiry = new Enquiry();

                List<Enquiry> enquiryList = Arrays.asList(gson.fromJson(response, Enquiry[].class));
                for (Enquiry enqu : enquiryList) 
                    detailEnquiry = enqu;
                
                forwardToViewEnquiryMoreDetails(detailEnquiry);

                /*Log.d("e", "All data inserted...now display.........");
                List<Enquiry> enqlist= EnquiryORM.getEnquiries(getBaseContext());
                for(Enquiry i:enqlist) 
                    Log.d("e", "enquiry :" +i.getId());
                    Log.d("e", i.getName()+","+i.getStatus()+","+i.getAddress()+","+i.getUser_id());
                
*/
            
        , new Response.ErrorListener() 
            @Override
            public void onErrorResponse(VolleyError error) 

                Log.e("EnqViewActivity", error.toString());
                Toast.makeText(getApplicationContext(), "Error: " + error.getMessage(), Toast.LENGTH_LONG).show();
            
        ) 
            @Override
            protected Map<String, String> getParams() throws AuthFailureError 

                Log.d("d", "inside getparams()...\n");
                Map<String, String> params = new HashMap<String, String>();
                params.put("enquiryid", String.valueOf(enId));
                params.put("userid", String.valueOf(uid));
                Log.d("d", "enquiry id to pass:" + enId + "\n");
                return params;
            
        ;

        // Add the request to RequestQueue.
        // MyVolleySingleton.getInstance(this).addToRequestQueue(sr);
        requestQueue.add(sr);
        Log.d("d", "Added to queue");
    

//-----------------------------------------------------------------------

    private void forwardToViewEnquiryMoreDetails(Enquiry detailedEnquiry) 

        Gson mynewgson = new Gson();
        String DEnquiryDataObjectAsString = mynewgson.toJson(detailedEnquiry);

        Intent toDetail = new Intent(EnquiryViewActivity.this, EnquiryViewMoreActivity.class);
        toDetail.putExtra("DetailedEnquiryDataObjectAsString", DEnquiryDataObjectAsString);
        startActivity(toDetail);
        // close this activity
        //finish();
    

    private String getDateTime() 
        SimpleDateFormat dateFormat = new SimpleDateFormat(
                "yyyy-MM-dd HH:mm:ss", Locale.getDefault());
        Date date = new Date();
        return dateFormat.format(date);

    

    //---------------------------------------------------------------

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.view_enq, menu);
        return true;
    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in androidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_add_enquiry) 
            startActivity(new Intent(EnquiryViewActivity.this, EnquiryAddActivity.class));
            return true;
        
        if (id == R.id.action_edit_enquiry) 
            // Make all fields editable
            contactFragment.enableAllViews();
            return true;
        

        return super.onOptionsItemSelected(item);
    


片段代码是:

public class ContactFragment extends Fragment implements View.OnClickListener 

    private IFragmentToActivity mCallback;

    Button btn_MoreEnqDetails, btn_ToSiteVisit, btn_nextEnq1;
    EditText etName, etAddress, etSiteAddress, etPhoneNo, etMob, etEmail;

    public ContactFragment() 
        // Required empty public constructor
    

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_contact, container, false);

        btn_MoreEnqDetails = (Button) view.findViewById(R.id.btn_MoreEnqDetails);
        btn_ToSiteVisit = (Button) view.findViewById(R.id.btn_ToSiteVisit);
        btn_nextEnq1 = (Button) view.findViewById(R.id.btn_nextEnq1);

        etName = (EditText) view.findViewById(R.id.etClientName);
        etAddress = (EditText) view.findViewById(R.id.etAddress);
        etSiteAddress = (EditText) view.findViewById(R.id.etSiteAddress);
        etPhoneNo = (EditText) view.findViewById(R.id.etPhoneNo);
        etMob = (EditText) view.findViewById(R.id.etMob);
        etEmail = (EditText) view.findViewById(R.id.etEmail);

        btn_MoreEnqDetails.setOnClickListener(this);
        btn_ToSiteVisit.setOnClickListener(this);
        btn_nextEnq1.setOnClickListener(this);

        return view;
    

    @Override
    public void onClick(View v) 

        switch (v.getId()) 
            case R.id.btn_MoreEnqDetails:
                mCallback.showToast("Hello from Fragment 1");
                break;

            case R.id.btn_ToSiteVisit:
                mCallback.gotoSiteVisit();
                break;

            case R.id.btn_nextEnq1:
                Enquiry enq=new Enquiry();
                enq=getDataFromViews(enq);
                mCallback.saveDataContacts(enq);
                break;
        

    

    @Override
    public void onAttach(Context context) 
        super.onAttach(context);
        try 
            mCallback = (IFragmentToActivity) context;
         catch (ClassCastException e) 
            throw new ClassCastException(context.toString()
                    + " must implement IFragmentToActivity");
        
    

    @Override
    public void onDetach() 
        mCallback = null;
        super.onDetach();
    

    public void onRefresh() 
        Toast.makeText(getActivity(), "Fragment 1: Refresh called.",
                Toast.LENGTH_SHORT).show();
    


    public void disableAllViews() 

        Log.d("EnqViewAct: ", "disabling all views..");
        btn_MoreEnqDetails.setEnabled(false);
        btn_ToSiteVisit.setEnabled(false);
        btn_nextEnq1.setEnabled(false);
        etName.setEnabled(false);
        etAddress.setEnabled(false);
        etSiteAddress.setEnabled(false);
        etPhoneNo.setEnabled(false);
        etMob.setEnabled(false);
        etEmail.setEnabled(false);

    

    public void enableAllViews() 

        Log.d("EnqViewAct: ", "enabling all views..");
        btn_MoreEnqDetails.setEnabled(true);
        btn_ToSiteVisit.setEnabled(true);
        btn_nextEnq1.setEnabled(true);
        etName.setEnabled(true);
        etAddress.setEnabled(true);
        etSiteAddress.setEnabled(true);
        etPhoneNo.setEnabled(true);
        etMob.setEnabled(true);
        etEmail.setEnabled(true);

    

    public void setDataToScreen(Enquiry enquiry) 

        Log.d("EbqViewAct","Data to display : "
                +enquiry.getId()+","+enquiry.getUser_id()+","+
                enquiry.getStatus()+","+enquiry.getEnqstatusnew()+","+
                enquiry.getCreateddate()+","+
                enquiry.getName()+","+enquiry.getAddress()+","+
                enquiry.getSiteaddress()+","+enquiry.getPhone_number()+","+
                enquiry.getMobile_number()+","+enquiry.getEmail());

        if(enquiry.getName()!=null && enquiry.getName()!="")
        etName.setText(enquiry.getName());
        if(enquiry.getAddress()!=null && enquiry.getAddress()!="")
        etAddress.setText(enquiry.getAddress());
        if(enquiry.getSiteaddress()!=null && enquiry.getSiteaddress()!="")
        etSiteAddress.setText(enquiry.getSiteaddress());
        if(enquiry.getPhone_number()!=null && enquiry.getPhone_number()!="")
        etPhoneNo.setText(enquiry.getPhone_number());
        if(enquiry.getMobile_number()!=null && enquiry.getMobile_number()!="")
        etMob.setText(enquiry.getMobile_number());
        if(enquiry.getEmail()!=null && enquiry.getEmail()!="")
        etEmail.setText(enquiry.getEmail());

       /* if (thisSv.getFamilytype() != null) 
            if (thisSv.getFamilytype().equalsIgnoreCase("Nuclear")) 
                rgrp_familyType.check(R.id.rbtn_nuclear);
             else if (thisSv.getFamilytype().equalsIgnoreCase("Join")) 
                rgrp_familyType.check(R.id.rbtn_join);
             else 
                rgrp_familyType.check(R.id.rbtn_nuclear);
            
        */

    

    public Enquiry getDataFromViews(Enquiry enq) 

      /*
        radioSelectedFamilyType = (RadioButton) findViewById(rgrp_familyType.getCheckedRadioButtonId());
        if (radioSelectedFamilyType != null) 
            newSv.setFamilytype(radioSelectedFamilyType.getText().toString());
        */

        if ((etName.getText().toString()) != "" && (etName.getText().toString()) != null) 
            enq.setName(etName.getText().toString().trim());
        
        if ((etAddress.getText().toString()) != "" && (etAddress.getText().toString()) != null) 
            enq.setAddress(etAddress.getText().toString().trim());
        
        if ((etSiteAddress.getText().toString()) != "" && (etSiteAddress.getText().toString()) != null) 
            enq.setSiteaddress(etSiteAddress.getText().toString().trim());
        
        if ((etPhoneNo.getText().toString()) != "" && (etPhoneNo.getText().toString()) != null) 
            enq.setPhone_number(etPhoneNo.getText().toString().trim());
        
        if ((etMob.getText().toString()) != "" && (etMob.getText().toString()) != null) 
            enq.setMobile_number(etMob.getText().toString().trim());
        
        if ((etEmail.getText().toString()) != "" && (etEmail.getText().toString()) != null) 
            enq.setEmail(etEmail.getText().toString().trim());
        
        return enq;
    



    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) 
    


界面是:

public interface IFragmentToActivity 

    void showToast(String msg);
    void communicateToFragment2();

    void gotoMoreDetails();
    void gotoSiteVisit();
    void saveDataContacts(Enquiry enq);


PagerAdapter 是:

public class ViewPagerAdapter extends FragmentStatePagerAdapter 

    private final SparseArray<WeakReference<Fragment>> instantiatedFragments = new SparseArray<>();
    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager manager) 
        super(manager);
    

    @Override
    public Fragment getItem(int position) 
        return mFragmentList.get(position);
    

    @Override
    public int getCount() 
        return mFragmentList.size();
    

    public void addFragment(Fragment fragment, String title) 
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    

    @Override
    public CharSequence getPageTitle(int position) 
        return mFragmentTitleList.get(position);
    

    @Override
    public int getItemPosition(Object object)
        return super.getItemPosition(object);

    
//--------------------------------------------------------

    @Override
    public Object instantiateItem(final ViewGroup container, final int position) 
        final Fragment fragment = (Fragment) super.instantiateItem(container, position);
        instantiatedFragments.put(position, new WeakReference<>(fragment));
        return fragment;
    

    @Override
    public void destroyItem(final ViewGroup container, final int position, final Object object) 
        instantiatedFragments.remove(position);
        super.destroyItem(container, position, object);
    

    @Nullable
    public Fragment getFragment(final int position) 
        final WeakReference<Fragment> wr = instantiatedFragments.get(position);
        if (wr != null) 
            return wr.get();
         else 
            return null;
        
    


错误日志是:

12-25 11:09:46.931 3136-3136/com.example.anjana.decorightkitchen E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                   Process: com.example.anjana.decorightkitchen, PID: 3136
                                                                                   java.lang.RuntimeException: Unable to start activity ComponentInfocom.example.anjana.decorightkitchen/com.example.anjana.decorightkitchen.activity.EnquiryViewActivity: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.EditText.setText(java.lang.CharSequence)' on a null object reference
                                                                                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
                                                                                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
                                                                                       at android.app.ActivityThread.-wrap11(ActivityThread.java)
                                                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
                                                                                       at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                       at android.os.Looper.loop(Looper.java:148)
                                                                                       at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                                                                    Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.EditText.setText(java.lang.CharSequence)' on a null object reference
                                                                                       at com.example.anjana.decorightkitchen.fragment.ContactFragment.setDataToScreen(ContactFragment.java:149)
                                                                                       at com.example.anjana.decorightkitchen.activity.EnquiryViewActivity.onCreate(EnquiryViewActivity.java:140)
                                                                                       at android.app.Activity.performCreate(Activity.java:6237)
                                                                                       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
                                                                                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
                                                                                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
                                                                                       at android.app.ActivityThread.-wrap11(ActivityThread.java) 
                                                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
                                                                                       at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                                       at android.os.Looper.loop(Looper.java:148) 
                                                                                       at android.app.ActivityThread.main(ActivityThread.java:5417) 
                                                                                       at java.lang.reflect.Method.invoke(Native Method) 
                                                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                                                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

注意:查询对象值正确进入片段。 enqName.setText("hai") 在片段的 onCreateView() 内正常工作。 但是当enqName.setText("hai")放到fragment的一个公共方法中,并从onCreateView()中调用该方法时,再次出现nullpointer异常。

【问题讨论】:

也发布您的错误日志 编辑添加错误日志@Tej 您收到您的数据enquiry.getName() 了吗?在您的联系人片段中? 是的...我在联系人片段@Tej 中获取查询对象数据 那么可能是你的edittext初始化问题。所以请确保您的所有编辑文本中的findViewbyId 带有他们受人尊敬的 ID 【参考方案1】:

来自您的代码和错误日志

void android.widget.EditText.setText(java.lang.CharSequence)' on a null object reference

似乎,可能只有两个问题。

    您的 Edittext 初始化问题,可能与您的 finViewByID 或您的 身份证名称(R.id.checkthis) 当您启用和禁用视图时。所以当你 setText ,您的视图是Enable 而不是Visibility.Gone

正如您已经检查了您的 enquiry 对象。它运作良好。所以我认为这些可能导致NullPointerException

【讨论】:

删除启用和禁用方法无效!【参考方案2】:

也许您正在寻找这样的东西。?

  Fragment home = getSupportFragmentManager().findFragmentById(R.id.content_frame);
                    if (home instanceof HomeFragment) 
                        ((HomeFragment)home).setData(data);
                    

【讨论】:

【参考方案3】:

要在创建时将数据发送到片段,您可以在创建片段时为片段设置参数,然后您可以像这样稍后检索它:

public static ContactFragment newInstance(String data, int data2) 
        ContactFragment  fragment = new ContactFragment();
        Bundle bundle = new Bundle();
        bundle.putString("someData", data);
        bundle.putInt("otherData", data2);
        fragment.setArguments(bundle);
        return fragment;
    

当你调用你的片段时,像这样使用这个构造函数:

ContactFragment fragment = ContactFragment.newInstance("firstData",1200);

在您的片段中,您可以像这样在任何地方检索数据:

int variable = getArguments().getInt("otherData");
String string = getArguments().getString("someData");

希望这会有所帮助。

【讨论】:

以上是关于访问片段的子视图时出现空指针异常的主要内容,如果未能解决你的问题,请参考以下文章

Android ViewBinding 有时会在绑定对象处返回 null,因此在尝试访问视图时出现空指针异常

在使用ViewPager时尝试从其父活动修改片段时出现空指针异常

Android:小部件 - 在远程视图上使用 setOnclickPendingIntent 时出现空指针异常?

尝试从 Kotlin 中的另一个活动访问 EditText 时出现空指针异常

Android - 调用自定义 View 方法时出现空指针异常

在 C++ 中使用链表时出现空指针异常