前言:我使用的是 ActionBarSherlock,Target SDK 是 17(Android 4.2),Min SDK 是 5(Android 2.0)
情况:
我的应用程序中有一个片段,它提供了某种登录。它允许用户在设备上拥有多个用户帐户(因为 Android < 4.2 没有系统支持,而我们的用户似乎由于设备共享而使用它)。
片段布局由一个列表视图和一个大景观组成,还有一个添加新帐户的按钮(否则通过可用的溢出菜单)。
listview 附加到一个名为“AccountAdapter”的 BaseAdapter-Derivate,它从数据库中获取帐户并通过 layoutinflater 为每个帐户创建相应的子视图。有 3 种可能性:用户提供了登录名和密码/用户只提供了登录名/用户什么也没提供。因此,对于这些情况,有 3 种不同的布局,其中丢失的数据是通过 EditText-Elements 请求的,而存储的数据是通过 TextView 显示的。此外,缺少数据的布局提供了一个用于存储缺失数据的复选框和一个提交按钮。如果提供了所有数据,则缺少提交按钮的 onclicklistener 将直接附加到帐户根视图。onclicklistener 将输入的数据消息发送到网络代码类并修改适配器模式;之后,适配器只显示选定的条目,
这已经很好了。
问题:
在方向更改时,所有输入的数据都会丢失。输入的登录数据、密码、有关是否应存储登录数据的信息。
布局:
<!-- layout/main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="@id/main_fragment_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!-- layout-large-land/main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="@id/main_fragment_sidebar"
android:layout_width="@dimen/main_sidebar_width"
android:layout_height="match_parent" />
<FrameLayout
android:id="@id/main_fragment_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!-- layout/fragment_login.xml -->
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="@id/fragment_login_accountlist"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</RelativeLayout>
<!-- layout-large-land/fragment_login.xml -->
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@id/fragment_login_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="@string/string_fragment_login" />
<ListView
android:id="@id/fragment_login_accountlist"
android:layout_width="@dimen/fragment_login_accountlist_width"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" >
</ListView>
</RelativeLayout>
<!-- layout/view_login_account_new.xml -->
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@id/view_login_account_profileimage"
android:layout_width="@dimen/view_login_account_profileimage_width"
android:layout_height="@dimen/view_login_account_profileimage_height"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:contentDescription="@string/string_view_login_account_profileimage_contentdescription"
android:scaleType="fitCenter"
android:src="@drawable/img_kb" />
<EditText
android:id="@id/view_login_account_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_toRightOf="@id/view_login_account_profileimage"
android:ems="10"
android:hint="@string/string_view_login_account_username_hint"
android:inputType="text" >
<requestFocus />
</EditText>
<EditText
android:id="@id/view_login_account_password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/view_login_account_username"
android:layout_alignParentRight="true"
android:layout_below="@id/view_login_account_username"
android:ems="10"
android:hint="@string/string_view_login_account_password_hint"
android:inputType="textPassword" />
<CheckBox
android:id="@id/view_login_account_storecredentials"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@id/view_login_account_password"
android:layout_toRightOf="@id/view_login_account_profileimage"
android:text="@string/string_view_login_account_storecredentials_text" />
<Button
android:id="@id/view_login_account_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@id/view_login_account_storecredentials"
android:text="@string/string_view_login_account_submit_text" />
</RelativeLayout>
<!-- layout/view_login_account_progress.xml -->
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@id/view_login_account_profileimage"
android:layout_width="@dimen/view_login_account_profileimage_width"
android:layout_height="@dimen/view_login_account_profileimage_height"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:contentDescription="@string/string_view_login_account_profileimage_contentdescription"
android:scaleType="fitCenter"
android:src="@drawable/img_kb" />
<TextView
android:id="@id/view_login_account_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_toRightOf="@id/view_login_account_profileimage"
android:ems="10"
>
</TextView>
<TextView
android:id="@id/view_login_account_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/view_login_account_username"
android:layout_alignParentRight="true"
android:layout_below="@id/view_login_account_username"
android:ems="10"
android:text="@string/string_view_login_account_progress_text" />
</RelativeLayout>
<!-- layout/view_login_account_stored_password.xml -->
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@id/view_login_account_profileimage"
android:layout_width="@dimen/view_login_account_profileimage_width"
android:layout_height="@dimen/view_login_account_profileimage_height"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:contentDescription="@string/string_view_login_account_profileimage_contentdescription"
android:scaleType="fitCenter"
android:src="@drawable/img_kb" />
<TextView
android:id="@id/view_login_account_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_toRightOf="@id/view_login_account_profileimage"
android:ems="10"
>
</TextView>
<TextView
android:id="@id/view_login_account_password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/view_login_account_username"
android:layout_alignParentRight="true"
android:layout_below="@id/view_login_account_username"
android:ems="10"
android:text="@string/string_view_login_account_password_text"
/>
</RelativeLayout>
<!-- layout/view_login_account_stored_username.xml -->
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@id/view_login_account_profileimage"
android:layout_width="@dimen/view_login_account_profileimage_width"
android:layout_height="@dimen/view_login_account_profileimage_height"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:contentDescription="@string/string_view_login_account_profileimage_contentdescription"
android:scaleType="fitCenter"
android:src="@drawable/img_kb" />
<TextView
android:id="@id/view_login_account_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_toRightOf="@id/view_login_account_profileimage"
android:ems="10"
android:hint="@string/string_view_login_account_username_hint" >
<requestFocus />
</TextView>
<EditText
android:id="@id/view_login_account_password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/view_login_account_username"
android:layout_alignParentRight="true"
android:layout_below="@id/view_login_account_username"
android:ems="10"
android:hint="@string/string_view_login_account_password_hint"
android:inputType="textPassword" />
<CheckBox
android:id="@id/view_login_account_storecredentials"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@id/view_login_account_password"
android:layout_toRightOf="@id/view_login_account_profileimage"
android:text="@string/string_view_login_account_storecredentials_text" />
<Button
android:id="@id/view_login_account_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@id/view_login_account_storecredentials"
android:text="@string/string_view_login_account_submit_text" />
</RelativeLayout>
代码:
代码都没有实现 onSaveInstanceState 和 onConfigurationChange。(整个引用会太长恕我直言,> 1.000 行代码)
public class MessengerActivity extends SherlockFragmentActivity {
// -------------------------------------------------------------------------
FrameLayout fragmentSidebar = null;
FrameLayout fragmentContent = null;
Content content = null;
// -------------------------------------------------------------------------
boolean hasSidebar = false;
// -------------------------------------------------------------------------
public void onCreate(Bundle savedInstanceState) {
// ---------------------------------------------------------------------
super.onCreate(savedInstanceState);
// ---------------------------------------------------------------------
content = Content.getInstance(this);
// ---------------------------------------------------------------------
setContentView(R.layout.main);
// ---------------------------------------------------------------------
captureFragmentViews();
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
if (savedInstanceState == null) {
// -----------------------------------------------------------------
gotoLogin();
// -----------------------------------------------------------------
}
else {
// -----------------------------------------------------------------
// -----------------------------------------------------------------
}
// ---------------------------------------------------------------------
}
// -------------------------------------------------------------------------
// Disabled through android manifest at the moment
@Override
public void onConfigurationChanged(Configuration newConfig) {
// ---------------------------------------------------------------------
super.onConfigurationChanged(newConfig);
// ---------------------------------------------------------------------
Log.d(getClass().getSimpleName(), "onConfigurationChanged");
// ---------------------------------------------------------------------
}
// -------------------------------------------------------------------------
public void captureFragmentViews() {
// ---------------------------------------------------------------------
fragmentSidebar = (FrameLayout) findViewById(R.id.main_fragment_sidebar);
fragmentContent = (FrameLayout) findViewById(R.id.main_fragment_content);
// ---------------------------------------------------------------------
if ((fragmentSidebar != null) && (fragmentContent != null)) {
hasSidebar = true;
}
else {
hasSidebar = false;
}
// ---------------------------------------------------------------------
}
// -------------------------------------------------------------------------
public void gotoLogin() {
// ---------------------------------------------------------------------
Fragment fragment = SherlockFragment.instantiate(this,
LoginFragment.class.getName());
// ---------------------------------------------------------------------
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (hasSidebar) {
ft.add(R.id.main_fragment_content, fragment);
fragmentSidebar.setVisibility(View.GONE);
}
else {
ft.add(R.id.main_fragment_content, fragment);
}
// ---------------------------------------------------------------------
ft.commit();
getSupportFragmentManager().executePendingTransactions();
// ---------------------------------------------------------------------
}
// -------------------------------------------------------------------------
public void gotoSignup() {
// TODO Auto-generated method stub
}
// -------------------------------------------------------------------------
public void gotoContactList(int filterId) {
// TODO Auto-generated method stub
}
// -------------------------------------------------------------------------
public void gotoConversation(int userId) {
// TODO Auto-generated method stub
}
// -------------------------------------------------------------------------
public void gotoOnlineStatusList(int categoryId) {
// TODO Auto-generated method stub
}
// -------------------------------------------------------------------------
public void gotoSettings(int categoryId) {
// TODO Auto-generated method stub
}
// -------------------------------------------------------------------------
}
我检查是否在主活动中设置了 savedInstanceState,所以我的活动已经在片段重新创建方面“准备好了”。
Fragment 在创建适配器并将其附加到列表视图之前检查适配器是否已经存在。但是:据我了解,即使“重新创建的”片段使用相同的适配器,“默认情况下”所有 getViews() 都会被调用,因此会创建一个具有“重置”内容的视图的新实例。
AccountAdapter 从数据库中获取具有用户 ID、用户名、密码的专用“帐户”对象。此外,“帐户”可以扩展以保存其他数据,例如缓存视图。
我的想法是实现这样的getView:
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// ---------------------------------------------------------------------
final Account account = (Account) getItem(position);
View view = null;
// ---------------------------------------------------------------------
if (account == null) {
return view;
}
// ---------------------------------------------------------------------
if (account.view != null) {
return account.view;
}
// ---------------------------------------------------------------------
[...]
}
但后来我注意到,AccountAdapter 没有在游戏中幸存下来,Android 重新实例化了 LoginFragment 类。
我需要的:
- 如何从列表视图内容公式中恢复数据/如何保留 AccountAdapter 及其关联视图
- 关于如何优化和改进我的建筑设计的提示