0

我开始开发基于 FragmentsBasic.zip 示例项目的应用程序:http: //developer.android.com/training/basics/fragments/index.html

在开始编写自己的代码之前,我导入了 ActionBarSherlock 并让一切按预期工作。

情况:我有一个主要的活动类(TaskListActivity)和3个片段类。在手机中运行应用程序时,TaskListActivity 首先加载 TaskListFragment,如果用户触摸操作栏中的“新任务”图标,它会将 TaskListFragment 替换为 NewTaskFragment。这个片段有一个布局,其中包含一个 EditText 和一个 Button View。当用户输入文本并按下“完成”按钮时,测试被添加到 ListView。

问题:只要不发生设备旋转,一切都会按预期工作。无论我在将项目添加到列表之前还是之后旋转设备,我都会收到以下错误,

10-18 23:19:40.838: E/TaskListActivity(2021): Fragment has a null value
10-18 23:19:40.848: E/AndroidRuntime(2021): FATAL EXCEPTION: main
10-18 23:19:40.848: E/AndroidRuntime(2021): java.lang.NullPointerException
10-18 23:19:40.848: E/AndroidRuntime(2021):     at com.sample.testapp.TasksListActivity.onNewTaskAdded(TasksListActivity.java:169)
10-18 23:19:40.848: E/AndroidRuntime(2021):     at com.sample.testapp.NewTaskFragment$2.onClick(NewTaskFragment.java:63)
10-18 23:19:40.848: E/AndroidRuntime(2021):     at android.view.View.performClick(View.java:2449)
10-18 23:19:40.848: E/AndroidRuntime(2021):     at android.view.View$PerformClick.run(View.java:9027)

我的活动如下所示:

public class TasksListActivity extends SherlockFragmentActivity 
        implements TasksListFragment.OnTaskSelectedListener,    NewTaskFragment.OnNewTaskAddedListener {

    private ArrayList<Task> tasks;
    private String taskName;
    private TasksListFragment firstFragment;


        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.tasks_list);

            if (findViewById(R.id.fragment_container) != null) {

                if (savedInstanceState != null) {
                    return;
                }

            firstFragment = new TasksListFragment();

            // In case this activity was started with special instructions from an Intent,
            // pass the Intent's extras to the fragment as arguments
            firstFragment.setArguments(getIntent().getExtras());

            // Add the fragment to the 'fragment_container' FrameLayout
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, firstFragment).commit();
        }
    }

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

        case R.id.menu_new:
            //Toast.makeText(this, "Tapped new task", Toast.LENGTH_SHORT).show();

            // try code from Fragment sample
            NewTaskFragment newTaskFragment = (NewTaskFragment)getSupportFragmentManager().findFragmentById(R.id.task_fragment);

            if(newTaskFragment != null){
                // if itemFragment is available we are in two-pane layout

                // Call method in NewItemFragment to update its content
                //itemFragment.
            }
            else{
                // if the frag is not available, we are in one-pane layout and must swap fragments

                // Create fragment and give it an argument for the selected article
                newTaskFragment = new NewTaskFragment();
                Bundle args = new Bundle();
                //args.putInt(NewItemFragment.ARG_POSITION, position);
                newTaskFragment.setArguments(args);
                FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

                // Replace whatever is in the fragment_container view wiht this fragment,
                // and add the transaction to the back stack so the user can navigate back
                transaction.replace(R.id.fragment_container, newTaskFragment);
                transaction.addToBackStack(null);

                // Commit the transaction
                transaction.commit();

            }
            break;
        }
        return super.onOptionsItemSelected(item);
    }
}

    public void onNewTaskAdded(String newItem){
        this.taskName = newItem;
        if(firstFragment == null){
            Log.e("TaskListActivity", "Fragment has a null value");
        }

        firstFragment.onItemAdded(this.taskName);  // This is line 169

        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.fragment_container, firstFragment);

        transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();

    }

NewItemFragment 具有以下内容(界面未显示):

public class NewTaskFragment extends SherlockFragment {

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

    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.new_task_fragment, container, false);

    int layout = R.layout.new_task_fragment;
    Log.v("NewTaskFragment", "The layout to use is (NewTask): " + layout);

    final EditText myEditText = (EditText)view.findViewById(R.id.newTask);
    final Button doneButton = (Button)view.findViewById(R.id.addNewTask);
    final InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);


    doneButton.setOnClickListener(new View.OnClickListener() {  
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            String newItem = myEditText.getText().toString();
            onNewTaskAddedListener.onNewTaskAdded(newItem);   // This is line 63
            myEditText.setText("");
            imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
        }
    });

    return view;

}

我已经用 NullPointerException 标记的注释行 169(活动)和 63(片段)突出显示。我在 onNewTaskAdded 上添加了一些代码,并且能够确认在旋转后片段的值为空。有人可以帮我找出为什么对象在旋转后变为空(因此出现 NullPointerException)?让我知道是否需要其他详细信息。谢谢!

4

1 回答 1

2

当你旋转你的设备时,它会强制调用 onCreate() 函数,并且 savedInstanceState != null 现在可能是真的。

如果你不想在它旋转时再次 onCreate(),你可以这样做:

首先,将此行添加到您的 androidmanifest.xml 中:

android:configChanges="orientation|keyboardHidden"

然后修改你的activity.java:

@Override  
public void onConfigurationChanged(Configuration newConfig) {  
  // TODO Auto-generated method stub  
  super.onConfigurationChanged(newConfig);  
  if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {  

  } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {  

  }  
}  
于 2012-10-19T05:07:40.927 回答