簡體   English   中英

嘗試在空對象引用上調用虛擬方法

[英]Attempt to invoke virtual method on a null object reference

這是我得到的錯誤:

03-11 08:27:48.513:E / AndroidRuntime(23647):java.lang.RuntimeException:無法啟動活動ComponentInfo {com.plan.yeahimin / com.plan.yeahimin.PlanDetailsActivity}:java.lang.NullPointerException:嘗試在空對象引用上調用虛擬方法'java.io.Serializable android.os.Bundle.getSerializable(java.lang.String)'

我理解它是由於變量的值為空,但我無法鍛煉原因。 它看起來像它的“EXTRA_NEW_PLAN”在getSerializable()的方法DetailsFragment但除此之外,我不知道。 我是Android的新手,所以很明顯,請原諒我,但任何幫助將不勝感激。

這是我的ListFragment代碼;

public class PlanListFragment extends ListFragment {

public final static String TAG = "com.plan.yeahimin.PlanListFragment";
public final static String EXTRA_NEW_PLAN = "com.plan.yeahimin.plan_id";

private Button mAddPlan;
private ArrayList<Plan> mPlansList;


public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
    View v = inflater.inflate(R.layout.empty_view_or_list_view, parent, false);
    ListView view = (ListView) v.findViewById(android.R.id.list);
    view.setEmptyView(v.findViewById(android.R.id.empty));

    mAddPlan = (Button) v.findViewById(R.id.add_a_plan);

    mAddPlan.setOnClickListener(new View.OnClickListener(){

        @Override
        public void onClick(View v) {
            Log.d(TAG, "add plan clicked");
            Plan plan = new Plan();
            Log.d(TAG, "new plan created");
            PlanArrayList.get(getActivity()).addPlans(plan);
            Log.d(TAG, "plan added to mPlansList");
            Intent i = new Intent(getActivity(), PlanDetailsActivity.class);
            i.putExtra(PlanDetailsFragment.EXTRA_NEW_PLAN, plan.getId());
            startActivity(i);
            return;
        }

    });
    return v;
}

public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);

    mPlansList = PlanArrayList.get(getActivity()).getPlans();
    //ArrayList<Plan> mPlansList = new ArrayList<Plan>();
    PlanArrayAdapter paa = new PlanArrayAdapter(mPlansList);
    setListAdapter(paa);

}

public class PlanArrayAdapter extends ArrayAdapter<Plan>{


    public PlanArrayAdapter(ArrayList<Plan> planList){ 
        super(getActivity(), 0, planList);

    }

    public View getView(int position, View convertView, ViewGroup parent){

    // Get the plan item for this position
    Plan plan = getItem(position);

    //If layout doesnt exist, inflate one
    if(convertView == null){
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.plan_list_fragment, parent, false);

    }

    TextView planTitle = (TextView) convertView.findViewById(R.id.plan_title);
    planTitle.setText(plan.getTitle());
    TextView planDate = (TextView) convertView.findViewById(R.id.plan_date);
    planDate.setText(plan.getDate().toString());

        return convertView;
    }

}

}

這是我的DetailsFragment代碼,該代碼從添加按鈕打開;

public class PlanDetailsFragment extends Fragment {

private static final String TAG = "com.plan.yeahimin.PlanDetailsFragment";
public static final String EXTRA_NEW_PLAN = "com.plan.yeahimin.plan_id";

private EditText mTitleField;
private Button mDateButton;
private Button mTimeButton;
private EditText mLocationField;
private EditText mAttendeesField;
private EditText mDescriptionField;
private Plan mPlan;
private ArrayList<Plan> mPlansList;

public static PlanDetailsFragment newInstance(UUID planId){


    Bundle args = new Bundle();
    args.putSerializable(EXTRA_NEW_PLAN, planId);
    PlanDetailsFragment f = new PlanDetailsFragment();
    f.setArguments(args);
    Log.d(TAG, "newInstance created");
    return f;

}

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

    UUID planId = (UUID)getArguments().getSerializable(EXTRA_NEW_PLAN);
    mPlan = PlanArrayList.get(getActivity()).getPlan(planId);
}

@Override
public View onCreateView (LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){

    View v = inflater.inflate(R.layout.plan_details_fragment, parent, false);

    mTitleField = (EditText)v.findViewById(R.id.plan_title);

    mLocationField = (EditText)v.findViewById(R.id.plan_location);
    mAttendeesField = (EditText)v.findViewById(R.id.plan_attendees);
    mDescriptionField = (EditText)v.findViewById(R.id.plan_description);
    mDateButton = (Button)v.findViewById(R.id.plan_date);
    mTimeButton = (Button)v.findViewById(R.id.plan_time);


    return v;
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
    inflater.inflate(R.menu.main_to_do, menu);

}

public boolean onOptionsItemSelected(MenuItem item){
    switch(item.getItemId()){

    case R.id.save_button:

        Log.d(TAG, "save button pressed");
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}

}

我認為您無法使用.newInstance()向Fragment發送任何參數,因為根據文檔,此方法不接受任何參數。 因此,即使您已重載.newInstance(UUID),系統也會調用.newInstance()(如果有調用,我會有一些疑問)。 另外請注意,您已使用.putExtra()將參數放入Intent,但不要從Intent中調用它。

實際上,將參數發送到Fragment的正確方法如下:

在調用方中(通常是一個Activity,但也許帶有另一個Fragment,就像您的示例一樣,它也可以工作,我不能肯定地說):

PlanDetailsFragment fragment = new PlanDetailsFragment();
Bundle args = new Bundle();
args.putSerializable(PlanDetailsFragment.TAG_NEW_PLAN, plan.getID());
fragment.setArguments(args);
getFragmentManager().beginTransaction().add(fragment, TAG_DETAILS_FRAGMENT).commit();

在片段中:

Bundle args = getArguments();
UUID planID = (UUID) args.getSerializable(TAG_NEW_PLAN);

它不是現成的代碼,您應該根據類和變量名稱,標簽所在的位置等對它進行修改。如果您希望從另一個片段中進行工作,則Activity方法的調用也可能需要進行一些更改。 這只是一個整體描述。

我的答案適用於兩個片段都在一個活動中的情況。 您對Intent的使用使我對此有所懷疑,但我並不完全理解。

您已將參數發送到Activity(PlanDetailsActivity)。

您應該通過newInstance()方法將參數發送給Fragment。

在您的PlainDetailsActivity中,您應該創建片段實例,例如:

UUID uuid = getIntent().getSerializableExtra(PlanDetailsFragment.EXTRA_NEW_PLAN);
PlanDetailsFragment f = PlanDetailsFragment.newInstance(uuid);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM