java - Fragment 中的 getActivity 在方向改变后为空(单 Pane 布局)

标签 java android android-fragments

我有一个问题,我找到的解决方案对我不起作用(检查 null 等)。

我有一个简单的 Activity ,它在横向模式下托管 2 个 fragment ,在纵向模式下托管 1 个框架布局。当我更改设备的方向然后再将其改回来时,点击处理程序不起作用(DetailFragment 中的 getActivity() 为空)。

到目前为止,这是我的代码:

//UserListActivity.java
public class UserListActivity extends AppCompatActivity implements UserListFragment.OnUserListSelectedListener {

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

        // Check whether the activity is using the layout version with
        // the fragment_container FrameLayout. If so, we must add the first fragment
        if (findViewById(R.id.fragment_container) != null) {

            // However, if we're being restored from a previous state,
            // then we don't need to do anything and should return or else
            // we could end up with overlapping fragments.
            if (savedInstanceState != null) {
                return;
            }

            UserListFragment fragment = new UserListFragment();

            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.add(R.id.fragment_container, fragment, "");
            fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
            fragmentTransaction.commit();
        }
    }   

    @Override
    public void onUserListSelected(User selectedUser) {
        UserDetailFragment userDetailFragment = (UserDetailFragment) getSupportFragmentManager().findFragmentById(R.id.user_detail_fragment);

        if (userDetailFragment != null) {
            // If detail frag is available, we're in two-pane layout...

            userDetailFragment.updateSelectedView(selectedUser);
        } else {
            // Otherwise, we're in the one-pane layout and must swap frags...

            //create detailFragment
            UserDetailFragment newFragment = new UserDetailFragment();
            Bundle args = new Bundle();
            args.putString(UserDetailFragment.ARG_SELECTED_USER, new Gson().toJson(selectedUser));
            newFragment.setArguments(args);

            //replace fragment
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container, newFragment, "");
            fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();
        }
    }
}

//UserListFragment.java
public class UserListFragment extends ListFragment implements AdapterView.OnItemClickListener {    

    private OnUserListSelectedListener mCallback;
    private User[] users;   

    public interface OnUserListSelectedListener {
        void onUserListSelected(User selectedUser);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.user_list_fragment, container, false);
    }

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

        if (users == null) {
            getAllUsers();
        } else {
            setAdapter();
        }

        getListView().setOnItemClickListener(this);
    }

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

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (OnUserListSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnUserListSelectedListener");
        }
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        mCallback.onUserListSelected(users[position]);
    }

    private void setAdapter() {
        setListAdapter(new UserListAdapter(getActivity(), R.layout.user_list_row, users));
    }

    private void getAllUsers() {
        try {
            //...
            //Async webCall using volley
            //...
            users = tmp.getUsers().toArray(new User[tmp.getUsers().size()]);
            setAdapter();
            //...
    }
}

//UserDetailFragment.java
public class UserDetailFragment extends Fragment {
    final public static String ARG_SELECTED_USER = "selectedUser";
    private User mSelectedUser;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            mSelectedUser = new Gson().fromJson(savedInstanceState.getString(ARG_SELECTED_USER), User.class);
        }

        return inflater.inflate(R.layout.user_detail_fragment, container, false);
    }    

    @Override
    public void onStart() {
        super.onStart();
        Bundle args = getArguments();
        if (args != null) {
            updateSelectedView(new Gson().fromJson(args.getString(ARG_SELECTED_USER), User.class));
        } else {
            updateSelectedView(null);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putString(ARG_SELECTED_USER, new Gson().toJson(mSelectedUser));
    }

    public void updateSelectedView(User selectedUser) {
        //??? WHY IS GETACTIVITY() AFTER CHANGE OF ORIENTATION NULL ???
        if (getActivity() != null) {
            TextView textUserName = (TextView) getActivity().findViewById(R.id.textUserName);
            TextView textUserEmail = (TextView) getActivity().findViewById(R.id.textUserEmail);

            if (selectedUser != null) {
                textUserName.setText(selectedUser.getName());
                textUserEmail.setText(selectedUser.getEmail());
                mSelectedUser = selectedUser;
            } else {
                textUserName.setText(null);
            }
        }
    }
}

最佳答案

UserDetailFragment userDetailFragment = (UserDetailFragment) getSupportFragmentManager().findFragmentById(R.id.user_detail_fragment);

创建一个新的 fragment 实例。

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

            // However, if we're being restored from a previous state, 
            // then we don't need to do anything and should return or else 
            // we could end up with overlapping fragments. 
            if (savedInstanceState != null) {
                return; 
            } 

            UserListFragment fragment = new UserListFragment();

            FragmentManager fragmentManager = getSupportFragmentManager(); 
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
            fragmentTransaction.add(R.id.fragment_container, fragment, "");
            fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 
            fragmentTransaction.commit(); 
        } 

正在重用 fragment 的旧实例。

因此,在调用 .add 时使用 getFragmentByTag() 并且不要将标签保留为空字符串 ("")

关于java - Fragment 中的 getActivity 在方向改变后为空(单 Pane 布局),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31337871/

相关文章:

java - 使用 spring 管理 Kafka 主题

java - 什么是烫发空间?

android - 忽略 Android *中现有应用程序的 SSL 证书*

android - PreferenceFragment 中的 SwitchPreference 正在重置值

java - 将变量发送到 Fragment 类中?

java - 如何使用QueryParser进行Lucene范围查询(IntPoint/LongPoint)

java - 在 Java 中使用随机类的简单抛硬币。 do while 循环似乎不会生成随机结果

android - 手动更新联系人的 ContentObserver

php - 将 android AsyncHttpClient 中的数组 POST 到 php

android-fragments - 如何在 Android 的单个片段中使用多个 View 模型?