屏幕旋转时出现空指针异常

3
我希望建立一个应用程序,不同的方向模式下有不同的布局。因此我像Android教程[此处为示例]一样构建了我的项目。但是有一个差异,这个教程是为不同尺寸(正常和大型)创建的,而我需要为各种方向模式(横屏,竖屏等)创建。现在,在方向改变期间我得到了一个NullPointerException 。这是我的代码:

HeadlinesFragment:

public class HeadlinesFragment extends ListFragment {

   OnHeadlineSelectedListener HeadlinesCallback;
   List<Person> personLista = new ArrayList<Person>();

   public interface OnHeadlineSelectedListener {
        public void onArticleSelected(Person person);
    }

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

        int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?
                android.R.layout.simple_list_item_activated_1 : android.R.layout.simple_list_item_1;

        //TESTOWE WYPENIENIE
        for(int i=0; i<10; i++){
            personLista.add(new Person("Imie"+i+"Nazwisko"+i,"email"+i+"@example"+i+".com"));
        }
        String[] niceTime = new String[personLista.size()];
        for(int i=0; i<personLista.size(); i++){
            niceTime[i] = personLista.get(i).getName();
        }
        //KONIEC

        setListAdapter(new ArrayAdapter<String>(getActivity(), layout, niceTime));
    }
    @Override
    public void onStart() {
        super.onStart();

        // When in two-pane layout, set the listview to highlight the selected list item
        // (We do this during onStart because at the point the listview is available.)
        if (getFragmentManager().findFragmentById(R.id.person_view) != null) {
            getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        }
    }

    @Override
    public void onAttach(Activity activity){
        super.onAttach(activity);

        try{
            HeadlinesCallback = (OnHeadlineSelectedListener)activity;
        }catch(ClassCastException e){
            throw new ClassCastException(activity.toString()
                    + " have to implement OnHeadlineSelectedListener");
        }
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id){
        HeadlinesCallback.onArticleSelected(personLista.get(position));

        getListView().setItemChecked(position, true);
    }

}

PersonFragment:

public class PersonFragment extends Fragment{
   public static Person person;
   ImageView icon;
   TextView text1;
   TextView text2;
   TextView text3;

    View view;
   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container, 
        Bundle savedInstanceState) {

       if(savedInstanceState != null){
           person = (Person)savedInstanceState.getSerializable("person");
       }

       view = inflater.inflate(R.layout.person_view, container, false);

       icon = (ImageView)view.findViewById(R.id.icon);
       text1 = (TextView)view.findViewById(R.id.name);
       text2 = (TextView)view.findViewById(R.id.email);
       text3 = (TextView)view.findViewById(R.id.info);

       return view;
    }
    @Override
    public void onStart() {
        super.onStart();

        Bundle args = getArguments();
        if (args != null) {
            person = (Person)args.getSerializable("context");

            text1.setText(person.getName());
            text2.setText(person.getEmail());
            text3.setText("Quisque semper ultricies iaculis. Vestibulum nec metus adipiscing, egestas sem mattis, ornare nulla. Quisque nec nibh nec lacus euismod gravida. Proin at pretium enim. In auctor, nisi sit amet pharetra facilisis, est justo mattis mi, eget mattis tortor ligula non orci. Vestibulum neque augue, elementum vitae aliquam non, condimentum ac dui. Nullam ultricies velit nec diam aliquam, sed lacinia sem eleifend. Quisque quam sapien, sodales id suscipit nec, consequat vel nunc. Quisque eu velit nisi. Donec varius consequat metus, tempor semper tortor ultricies vel. Mauris eget arcu nisi. Proin sit amet dui nisl. Quisque auctor lobortis augue sit amet egestas. Fusce mattis aliquam ante, et bibendum nibh ullamcorper et. Integer ipsum nibh, placerat a felis ut, accumsan rutrum eros. Quisque lacinia facilisis ipsum sed commodo.");
            icon.setImageResource(R.drawable.ic_launcher);

        }else{
            if(person==null){
                person = new Person("Test Testowy", "Testowy@gmail.com");
            }
            updateArticleView(person);
        }
    }
    @Override
    public void onSaveInstanceState(Bundle outState){
        super.onSaveInstanceState(outState);
        outState.putSerializable("person", person);
    }
    public void updateArticleView(Person externalPerson) {
        this.person = externalPerson;

        text1.setText(externalPerson.getName());
        text2.setText(externalPerson.getEmail());
        text3.setText("Quisque semper ultricies iaculis. Vestibulum nec metus adipiscing, egestas sem mattis, ornare nulla. Quisque nec nibh nec lacus euismod gravida. Proin at pretium enim. In auctor, nisi sit amet pharetra facilisis, est justo mattis mi, eget mattis tortor ligula non orci. Vestibulum neque augue, elementum vitae aliquam non, condimentum ac dui. Nullam ultricies velit nec diam aliquam, sed lacinia sem eleifend. Quisque quam sapien, sodales id suscipit nec, consequat vel nunc. Quisque eu velit nisi. Donec varius consequat metus, tempor semper tortor ultricies vel. Mauris eget arcu nisi. Proin sit amet dui nisl. Quisque auctor lobortis augue sit amet egestas. Fusce mattis aliquam ante, et bibendum nibh ullamcorper et. Integer ipsum nibh, placerat a felis ut, accumsan rutrum eros. Quisque lacinia facilisis ipsum sed commodo.");
        icon.setImageResource(R.drawable.ic_launcher);

    }

}

以及 MainActivity:

public class MainActivity extends FragmentActivity implements OnHeadlineSelectedListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if(findViewById(R.id.fragment_container)!=null){

        if (savedInstanceState != null) {
            return;
        }

        getSupportFragmentManager().beginTransaction()
            .add(R.id.fragment_container, new HeadlinesFragment()).commit();

    }


}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}
@Override
public void onArticleSelected(Person person) {

    PersonFragment fragment = (PersonFragment)getSupportFragmentManager().findFragmentById(R.id.person_view);

    if(fragment!=null){
        fragment.updateArticleView(person);
    }else{
        PersonFragment newFragment = new PersonFragment();

        Bundle args = new Bundle();
        args.putSerializable("context", person);
        newFragment.setArguments(args);

        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.fragment_container, newFragment);
        transaction.addToBackStack(null);

        transaction.commit();
    }
}

问题: 一开始一切正常,但是当我把方向模式改成横屏(在模拟器中使用ctrl+f12),然后再改回竖屏,并从listview中选择一些东西时,就会出现“不幸地应用程序已停止”的提示。

这是logcat:

11-02 14:29:03.396: E/AndroidRuntime(802): FATAL EXCEPTION: main
11-02 14:29:03.396: E/AndroidRuntime(802): java.lang.NullPointerException
11-02 14:29:03.396: E/AndroidRuntime(802):  at com.example.friendslist.PersonFragment.updateArticleView(PersonFragment.java:68)
11-02 14:29:03.396: E/AndroidRuntime(802):  at com.example.friendslist.MainActivity.onArticleSelected(MainActivity.java:43)
11-02 14:29:03.396: E/AndroidRuntime(802):  at com.example.friendslist.HeadlinesFragment.onListItemClick(HeadlinesFragment.java:69)
11-02 14:29:03.396: E/AndroidRuntime(802):  at android.support.v4.app.ListFragment$2.onItemClick(ListFragment.java:58)
11-02 14:29:03.396: E/AndroidRuntime(802):  at android.widget.AdapterView.performItemClick(AdapterView.java:298)
11-02 14:29:03.396: E/AndroidRuntime(802):  at android.widget.AbsListView.performItemClick(AbsListView.java:1100)
11-02 14:29:03.396: E/AndroidRuntime(802):  at android.widget.AbsListView$PerformClick.run(AbsListView.java:2749)
11-02 14:29:03.396: E/AndroidRuntime(802):  at android.widget.AbsListView$1.run(AbsListView.java:3423)
11-02 14:29:03.396: E/AndroidRuntime(802):  at android.os.Handler.handleCallback(Handler.java:725)
11-02 14:29:03.396: E/AndroidRuntime(802):  at android.os.Handler.dispatchMessage(Handler.java:92)
11-02 14:29:03.396: E/AndroidRuntime(802):  at android.os.Looper.loop(Looper.java:137)
11-02 14:29:03.396: E/AndroidRuntime(802):  at android.app.ActivityThread.main(ActivityThread.java:5041)
11-02 14:29:03.396: E/AndroidRuntime(802):  at java.lang.reflect.Method.invokeNative(Native Method)
11-02 14:29:03.396: E/AndroidRuntime(802):  at java.lang.reflect.Method.invoke(Method.java:511)
11-02 14:29:03.396: E/AndroidRuntime(802):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
11-02 14:29:03.396: E/AndroidRuntime(802):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
11-02 14:29:03.396: E/AndroidRuntime(802):  at dalvik.system.NativeStart.main(Native Method)

我的主要问题是我总是在寻找“由...引起”的原因,但这里没有。有人能告诉我问题出在哪里吗?

附注:在正常的Android示例中,当我将子文件夹的名称从layout-large更改为layout-land时,我遇到了相同的问题。

活动:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />

person_view:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp" >

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" 
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/icon"
        android:layout_width="72dp"
        android:layout_height="74dp"
        android:src="@drawable/ic_launcher" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Imie i nazwisko" />
            <TextView
                android:id="@+id/email"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="email@sample.com" />

        </LinearLayout>

    </LinearLayout>

</LinearLayout>

<TextView
    android:id="@+id/info"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:text="info" />

位于land子文件夹中的主要活动:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

<fragment android:name="com.example.friendslist.HeadlinesFragment"
          android:id="@+id/headlines_fragment"
          android:layout_weight="1"
          android:layout_width="0dp"
          android:layout_height="match_parent" />

<fragment android:name="com.example.friendslist.PersonFragment"
          android:id="@+id/person_view"
          android:layout_weight="2"
          android:layout_width="0dp"
          android:layout_height="match_parent" />


java.lang.NullPointerException 11-02 14:06:14.696: E/AndroidRuntime(746): 在com.example.friendslist.PersonFragment.updateArticleView(PersonFragment.java:66)处,正如Raghunandan所说,这是第一行 - 第66行。 - Simon
"icon = (ImageView)getActivity().findViewById(R.id.icon);" 这行代码是在 updateArticleView 方法中(PersonFragment 中的最后一个方法)调用 findViewById 方法的第一次引用。我该如何以其他方式获取 icon 的引用? - bkowalczyyk
@bkowalczyyk 将所有的初始化操作移至 onCreateView 中,例如 view = inflater.inflate(R.layout.person_view, container, false); icon = (ImageView)view.findViewById(R.id.icon); - Raghunandan
又出现了同样的问题,但有一个不同之处,现在我在text1.setText(externalPerson.getName());中有一个空指针.. 怎么可能会有空的textView... - bkowalczyyk
@bkowalczyyk,你在onCreateView中初始化了所有的视图吗?externalPerson是否已经被初始化了? - Raghunandan
显示剩余9条评论
1个回答

1

好的,经过解决这个问题的斗争,我找到了解决方案,我将onArticleSelected方法中的条件从(fragment!=null)改为findViewById(R.id.fragment_container)。我不知道为什么,在方向改变后,片段仍然存在,也许有人可以解释一下。

编辑:如果有人想要检查方向设置,再次检查某些元素是否等于null,可以更简单地完成,例如:getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接