将自定义 ArrayAdapter 保存在 Fragment 中的 savedInstanceState 中
Save Custom ArrayAdapter in savedInstanceState in Fragment
我一直在使用 Evernote API 的应用程序工作,它已经在工作,但现在我在不同的活动中包含 savedInstanceStates。他们都在工作至少一个。例如,当我在列表中显示 Evernote 中的笔记并且旋转屏幕时,列表视图将再次创建。我想保存它的实例。
我已经尝试使用 setRetainInstance(true) 但是当屏幕旋转时,Listview 就像冻结一样,我无法在其中切换或滚动它。我正在阅读其他 post,这是因为我添加了与 MainActivity 中调用的 set.OnClickListener 的交互,而在此 Fragment 中没有。
所以,我正在寻找一种方法来存储数组的 savedInstance,以便在我旋转屏幕或 inResume() 等时调用它。
这是我的代码(因为MainActivity太长所以我只是添加了相关的方法):
public class MainActivity extends AppCompatActivity implements NoteListFragment.OnFragmentInteractionListener,EvernoteLoginFragment.ResultCallback {
private EvernoteSession mEvernoteSession;
private static final EvernoteSession.EvernoteService EVERNOTE_SERVICE = EvernoteSession.EvernoteService.SANDBOX;
private NoteFilter filter = new NoteFilter();
private EvernoteNoteStoreClient noteStoreClient;
private static NoteListFragment noteFragment;
private DrawerLayout mDrawerLayout;
private int mSelectedNavItem;
private static final String KEY_SELECTED_NAV_ITEM = "KEY_SELECTED_NAV_ITEM";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
noteFragment = (NoteListFragment) getFragmentManager().findFragmentById(R.id.note_list);
if (noteFragment == null) {
noteFragment = new NoteListFragment();
getFragmentManager()
.beginTransaction()
.add(R.id.main_content, noteFragment)
.commit();
}
if (savedInstanceState != null) {
mSelectedNavItem = savedInstanceState.getInt(KEY_SELECTED_NAV_ITEM, mSelectedNavItem);
} else {
mSelectedNavItem = R.id.nav_item_update;
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (!isTaskRoot()) {
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.open_drawer, R.string.close_drawer);
mDrawerLayout.setDrawerListener(drawerToggle);
drawerToggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.navigationView);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem.setChecked(true);
onNavDrawerItemClick(menuItem.getItemId());
return true;
}
});
navigationView.getMenu().findItem(mSelectedNavItem).setChecked(true);
loginEvernote();
if (!mEvernoteSession.isLoggedIn()) {
mEvernoteSession.authenticate(this);
// finish();
return;
} else {
//this is comment because when it will be save correctly I don't need to call all times loadNotes
// if (savedInstanceState == null) {
loadNotes(filter);
// }
}
} protected void loadNotes(NoteFilter filter) {
noteStoreClient = mEvernoteSession.getEvernoteClientFactory().getNoteStoreClient();
noteStoreClient.findNotesAsync(filter, 0, 100, new EvernoteCallback<NoteList>() {
@Override
public void onSuccess(NoteList result) {
noteFragment.setNotes(result.getNotes());
Toast.makeText(getApplicationContext(), R.string.onSucessLoadToast, Toast.LENGTH_LONG).show();
Log.d(getClass().getSimpleName(), "notes: " + result);
}
@Override
public void onException(Exception exception) {
Log.e(getClass().getSimpleName(), "Error al recuperar las notas", exception);
}
});
}
现在是片段:
public class NoteListFragment extends Fragment implements AdapterView.OnItemClickListener {
private OnFragmentInteractionListener mListener;
private ListAdapter mAdapter;
private AbsListView mListView;
private List<Note> Notes;
private EvernoteSession mEvernoteSession;
private ArrayAdapter<NoteWrapped> adapter;
FloatingActionButton newNoteButton;
public NoteListFragment() {
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new ArrayAdapter<NoteWrapped>(getActivity(), android.R.layout.simple_list_item_1, android.R.id.text1);
//setRetainInstance(true);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_note_list, container, false);
mListView = (AbsListView) view.findViewById(android.R.id.list);
((AdapterView<ListAdapter>) mListView).setAdapter(mAdapter);
mListView.setOnItemClickListener(this);
newNoteButton = (FloatingActionButton) view.findViewById(R.id.fab);
newNoteButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
FragmentManager frmg = getFragmentManager();
frmg.beginTransaction()
.replace(R.id.main_content, new CreateNoteFragment())
.addToBackStack(null)
.commit();
}
});
return view;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (null != mListener) {
try {
mListener.onFragmentInteraction(Notes.get(position));
} catch (EDAMUserException e) {
e.printStackTrace();
} catch (EDAMSystemException e) {
e.printStackTrace();
} catch (EDAMNotFoundException e) {
e.printStackTrace();
} catch (TException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onResume(Bundle savedInstanceState);
public void onFragmentInteraction(Note note) throws EDAMUserException, EDAMSystemException, EDAMNotFoundException, TException, ExecutionException, InterruptedException;
}
public class NoteWrapped{
private final String title;
public NoteWrapped(Note note) {
this.title = note.getTitle();
}
@Override
public String toString() {
return title;
}
}
public void setNotes(List<Note> notes) {
this.Notes = notes;
adapter = (ArrayAdapter<NoteWrapped>) mAdapter;
adapter.clear();
for (Note note : notes) {
adapter.add(new NoteWrapped(note));
}
}
}
以防万一,.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />
<FrameLayout
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#E8F5E9"
android:fitsSystemWindows="false"
app:itemTextColor="@android:color/secondary_text_light"
app:menu="@menu/settings_header">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
已经修复。我在其他 post 中找到了答案,我只是改编以在 Fragment 中使用它。
Something like this:
@Override
public Object onRetainNonConfigurationInstance() {
return this.m_adapter.getItems();
}
And then in your onCreate():
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// more init stuff here
sResultsArr = (ArrayList<SearchItems>)getLastNonConfigurationInstance();
if(sResultArr == null) {
sResultsArray = new ArrayList<SearchItems>(); // or some other initialization
}
self.m_adapter = new ResultsAdapter(home.this, R.layout.listrow, sResultsArr,home.this);
// ...
}
我一直在使用 Evernote API 的应用程序工作,它已经在工作,但现在我在不同的活动中包含 savedInstanceStates。他们都在工作至少一个。例如,当我在列表中显示 Evernote 中的笔记并且旋转屏幕时,列表视图将再次创建。我想保存它的实例。
我已经尝试使用 setRetainInstance(true) 但是当屏幕旋转时,Listview 就像冻结一样,我无法在其中切换或滚动它。我正在阅读其他 post,这是因为我添加了与 MainActivity 中调用的 set.OnClickListener 的交互,而在此 Fragment 中没有。
所以,我正在寻找一种方法来存储数组的 savedInstance,以便在我旋转屏幕或 inResume() 等时调用它。
这是我的代码(因为MainActivity太长所以我只是添加了相关的方法):
public class MainActivity extends AppCompatActivity implements NoteListFragment.OnFragmentInteractionListener,EvernoteLoginFragment.ResultCallback {
private EvernoteSession mEvernoteSession;
private static final EvernoteSession.EvernoteService EVERNOTE_SERVICE = EvernoteSession.EvernoteService.SANDBOX;
private NoteFilter filter = new NoteFilter();
private EvernoteNoteStoreClient noteStoreClient;
private static NoteListFragment noteFragment;
private DrawerLayout mDrawerLayout;
private int mSelectedNavItem;
private static final String KEY_SELECTED_NAV_ITEM = "KEY_SELECTED_NAV_ITEM";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
noteFragment = (NoteListFragment) getFragmentManager().findFragmentById(R.id.note_list);
if (noteFragment == null) {
noteFragment = new NoteListFragment();
getFragmentManager()
.beginTransaction()
.add(R.id.main_content, noteFragment)
.commit();
}
if (savedInstanceState != null) {
mSelectedNavItem = savedInstanceState.getInt(KEY_SELECTED_NAV_ITEM, mSelectedNavItem);
} else {
mSelectedNavItem = R.id.nav_item_update;
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (!isTaskRoot()) {
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.open_drawer, R.string.close_drawer);
mDrawerLayout.setDrawerListener(drawerToggle);
drawerToggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.navigationView);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem.setChecked(true);
onNavDrawerItemClick(menuItem.getItemId());
return true;
}
});
navigationView.getMenu().findItem(mSelectedNavItem).setChecked(true);
loginEvernote();
if (!mEvernoteSession.isLoggedIn()) {
mEvernoteSession.authenticate(this);
// finish();
return;
} else {
//this is comment because when it will be save correctly I don't need to call all times loadNotes
// if (savedInstanceState == null) {
loadNotes(filter);
// }
}
} protected void loadNotes(NoteFilter filter) {
noteStoreClient = mEvernoteSession.getEvernoteClientFactory().getNoteStoreClient();
noteStoreClient.findNotesAsync(filter, 0, 100, new EvernoteCallback<NoteList>() {
@Override
public void onSuccess(NoteList result) {
noteFragment.setNotes(result.getNotes());
Toast.makeText(getApplicationContext(), R.string.onSucessLoadToast, Toast.LENGTH_LONG).show();
Log.d(getClass().getSimpleName(), "notes: " + result);
}
@Override
public void onException(Exception exception) {
Log.e(getClass().getSimpleName(), "Error al recuperar las notas", exception);
}
});
}
现在是片段:
public class NoteListFragment extends Fragment implements AdapterView.OnItemClickListener {
private OnFragmentInteractionListener mListener;
private ListAdapter mAdapter;
private AbsListView mListView;
private List<Note> Notes;
private EvernoteSession mEvernoteSession;
private ArrayAdapter<NoteWrapped> adapter;
FloatingActionButton newNoteButton;
public NoteListFragment() {
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new ArrayAdapter<NoteWrapped>(getActivity(), android.R.layout.simple_list_item_1, android.R.id.text1);
//setRetainInstance(true);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_note_list, container, false);
mListView = (AbsListView) view.findViewById(android.R.id.list);
((AdapterView<ListAdapter>) mListView).setAdapter(mAdapter);
mListView.setOnItemClickListener(this);
newNoteButton = (FloatingActionButton) view.findViewById(R.id.fab);
newNoteButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
FragmentManager frmg = getFragmentManager();
frmg.beginTransaction()
.replace(R.id.main_content, new CreateNoteFragment())
.addToBackStack(null)
.commit();
}
});
return view;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (null != mListener) {
try {
mListener.onFragmentInteraction(Notes.get(position));
} catch (EDAMUserException e) {
e.printStackTrace();
} catch (EDAMSystemException e) {
e.printStackTrace();
} catch (EDAMNotFoundException e) {
e.printStackTrace();
} catch (TException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onResume(Bundle savedInstanceState);
public void onFragmentInteraction(Note note) throws EDAMUserException, EDAMSystemException, EDAMNotFoundException, TException, ExecutionException, InterruptedException;
}
public class NoteWrapped{
private final String title;
public NoteWrapped(Note note) {
this.title = note.getTitle();
}
@Override
public String toString() {
return title;
}
}
public void setNotes(List<Note> notes) {
this.Notes = notes;
adapter = (ArrayAdapter<NoteWrapped>) mAdapter;
adapter.clear();
for (Note note : notes) {
adapter.add(new NoteWrapped(note));
}
}
}
以防万一,.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />
<FrameLayout
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#E8F5E9"
android:fitsSystemWindows="false"
app:itemTextColor="@android:color/secondary_text_light"
app:menu="@menu/settings_header">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
已经修复。我在其他 post 中找到了答案,我只是改编以在 Fragment 中使用它。
Something like this:
@Override public Object onRetainNonConfigurationInstance() { return this.m_adapter.getItems(); } And then in your onCreate(): @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); // more init stuff here sResultsArr = (ArrayList<SearchItems>)getLastNonConfigurationInstance(); if(sResultArr == null) { sResultsArray = new ArrayList<SearchItems>(); // or some other initialization } self.m_adapter = new ResultsAdapter(home.this, R.layout.listrow, sResultsArr,home.this); // ... }