Bây giờ chính xác là một tuần tôi cố gắng chuyển một ứng dụng dựa trên hoạt động đơn giản thành các đoạn. Tôi hoàn toàn bị mắc kẹt.Bị mắc kẹt khi chuyển từ hoạt động sang đoạn
Con thú này là một danh sách đơn giản, chi tiết, thêm/chỉnh sửa ứng dụng với contextmenu và menu tùy chọn. Tôi đã cố gắng làm cho nó đúng: Các mảnh vỡ và hoạt động trong mỗi tệp của riêng họ, sử dụng gói hỗ trợ v4 cho điện thoại và máy tính bảng, các mảnh vỡ làm mọi thứ mà một đoạn có thể sử dụng lại và các callbacks (rất nhiều) bay vòng quanh để thông báo cho các hoạt động và mảnh vỡ về những gì cần làm. Chuyển đổi từ SQLiteOpenHelper sang ContentProvider, chuyển đổi từ optionmenu thành actionbarmenu, và, và, và, ... (gần như tất cả mọi thứ tôi đã sử dụng sẽ không còn được dùng nữa).
Thật khủng khiếp. Ứng dụng dựa trên hoạt động đơn giản và nhỏ gọn của tôi có kích thước gần gấp 3 lần và rất nhiều thứ chưa hoạt động.
Nếu được yêu cầu, tôi có thể thêm mã của mình tại đây - nhưng có rất nhiều thứ (bạn đã được cảnh báo).
Câu hỏi của tôi: Có ai đó sẵn sàng chia sẻ một ví dụ hoàn chỉnh với Danh sách, Chi tiết VÀ Thêm/chỉnh sửa? Ví dụ này nên sử dụng các tệp riêng biệt cho Phân đoạn và Hoạt động (không phải là gói tất cả-trong-một từ Google).
Vui lòng không bỏ phiếu. Tôi thực sự muốn xem làm thế nào để làm cho nó đúng.
Rất cám ơn trước.
EDIT:
Đây là hoạt động khởi đầu với nó là hai bố trí (res/layout cho điện thoại và res/layout-lớn-đất cho máy tính bảng) và ContextMenu:
public class ActivityList extends FragmentActivity implements FragmentList.MyContextItemSelectedListener,
FragmentList.MyDeleteListener,
FragmentList.MyListItemClickListener,
FragmentList.MyOptionsItemSelectedListener,
FragmentDetails.MyDeleteListener,
FragmentDetails.MyOptionsItemSelectedListener {
@Override
public void myContextItemSelected(final int action, final long id) {
if (action == R.id.men_add) {
processEdit(0);
} else if (action == R.id.men_delete) {
processUpdateList();
} else if (action == R.id.men_details) {
processDetails(id);
} else if (action == R.id.men_edit) {
processEdit(id);
}
}
@Override
public void myDelete(final long id) {
processUpdateList();
}
@Override
public void myListItemClick(final long id) {
processDetails(id);
}
@Override
public void myOptionsItemSelected(final int action) {
myOptionsItemSelected(action, 0);
}
@Override
public void myOptionsItemSelected(final int action, final long id) {
if (action == R.id.men_add) {
processEdit(0);
} else if (action == R.id.men_edit) {
processEdit(id);
} else if (action == R.id.men_preferences) {
processPreferences();
}
}
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
processUpdateList();
}
@Override
public void onCreate(final Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activitylist);
}
private void processEdit(final long id) {
Intent intent = new Intent(this, ActivityEdit.class);
intent.putExtra("ID", id);
startActivityForResult(intent, MyConstants.DLG_TABLE1EDIT);
}
private void processDetails(final long id) {
if (Tools.isXlargeLand(getApplicationContext())) {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.right);
if (fragment == null ||
(fragment instanceof FragmentDetails && ((FragmentDetails) fragment).getCurrentId() != id)) {
fragment = new FragmentDetails(id);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.right, fragment);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.commit();
}
} else {
Intent intent = new Intent(this, ActivityDetails.class);
intent.putExtra("ID", id);
startActivityForResult(intent, MyConstants.DLG_TABLE1SHOW);
}
}
private void processPreferences() {
Intent intent = new Intent(this, MyPreferenceActivity.class);
startActivityForResult(intent, MyConstants.DLG_PREFERENCES);
}
private void processUpdateList() {
// TODO:
}
}
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<fragment
class="com.test.app.FragmentList"
android:id="@+id/fragmentlist"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:name="com.test.app.FragmentList" />
</LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<fragment
class="com.test.app.FragmentList"
android:id="@+id/fragmentlist"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_width="0dip"
android:name="com.test.app.FragmentList" />
<FrameLayout
android:id="@+id/right"
android:layout_height="match_parent"
android:layout_weight="2"
android:layout_width="0dip" />
</LinearLayout>
Đây là ListFragment với nó là bố trí liên tiếp, optionsmenu và ContextMenu:
public class FragmentList extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {
private SimpleCursorAdapter adapter;
private AlertDialog alertDialog;
private Context context;
private MyContextItemSelectedListener contextItemSelectedListener;
private MyDeleteListener deleteListener;
private long id;
private MyListItemClickListener listItemClickListener;
private ListView listView;
private MyOptionsItemSelectedListener optionsItemSelectedListener;
public interface MyContextItemSelectedListener {
public void myContextItemSelected(int action, long id);
}
public interface MyDeleteListener {
public void myDelete(long id);
}
public interface MyListItemClickListener {
public void myListItemClick(long id);
}
public interface MyOptionsItemSelectedListener {
public void myOptionsItemSelected(int action);
}
@Override
public void onActivityCreated(final Bundle bundle) {
super.onActivityCreated(bundle);
context = getActivity().getApplicationContext();
listView = getListView();
getActivity().getSupportLoaderManager().initLoader(MyConstants.LDR_TABLE1LIST, null, this);
adapter = new SimpleCursorAdapter(context,
R.layout.fragmentlist_row,
null,
new String[] { Table1.DESCRIPTION },
new int[] { R.id.fragmentlist_row_description },
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
setListAdapter(adapter);
setListShown(false);
registerForContextMenu(listView);
if (bundle != null && bundle.containsKey("ID")) {
id = bundle.getLong("ID");
listItemClickListener.myListItemClick(id);
}
if (Tools.isXlargeLand(context)) {
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
}
setHasOptionsMenu(true);
}
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
// Reduced: Check for implemented listeners
}
@Override
public boolean onContextItemSelected(final MenuItem menuItem) {
AdapterContextMenuInfo adapterContextMenuInfo = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
final long id = adapterContextMenuInfo.id;
if (menuItem.getItemId() == R.id.men_delete) {
processAlertDialog(id);
return true;
} else {
contextItemSelectedListener.myContextItemSelected(menuItem.getItemId(), adapterContextMenuInfo.id);
}
return super.onContextItemSelected(menuItem);
}
@Override
public void onCreateContextMenu(final ContextMenu contextMenu, final View view, final ContextMenuInfo contextMenuInfo) {
super.onCreateContextMenu(contextMenu, view, contextMenuInfo);
if (view.getId() == android.R.id.list) {
getActivity().getMenuInflater().inflate(R.menu.fragmentlist_context, contextMenu);
}
}
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle bundle) {
MyCursorLoader loader = null;
switch (id) {
case MyConstants.LDR_TABLE1LIST:
loader = new MyCursorLoader(context,
MySQLiteOpenHelper.TABLE1_FETCH,
null);
break;
}
return loader;
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater menuInflater) {
super.onCreateOptionsMenu(menu, menuInflater);
menu.clear();
menuInflater.inflate(R.menu.fragmentlist, menu);
}
@Override
public void onListItemClick(final ListView listView, final View view, final int position, final long id) {
super.onListItemClick(listView, view, position, id);
this.id = id;
if (Tools.isXlargeLand(context)) {
listView.setItemChecked(position, true);
}
listItemClickListener.myListItemClick(id);
}
@Override
public void onLoaderReset(final Loader<Cursor> loader) {
adapter.swapCursor(null);
}
@Override
public void onLoadFinished(final Loader<Cursor> loader, final Cursor cursor) {
adapter.swapCursor(cursor);
setListShown(true);
}
@Override
public boolean onOptionsItemSelected(final MenuItem menuItem) {
optionsItemSelectedListener.myOptionsItemSelected(menuItem.getItemId());
return super.onOptionsItemSelected(menuItem);
}
@Override
public void onSaveInstanceState(final Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putLong("ID", id);
}
private void processAlertDialog(final long id) {
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialogInterface, final int which) {
dialogInterface.dismiss();
}
});
alertDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialogInterface, final int which) {
MyApplication.getSqliteOpenHelper().deleteTable1(id);
alertDialog.dismiss();
deleteListener.myDelete(id);
}
});
alertDialogBuilder.setCancelable(false);
alertDialogBuilder.setMessage(R.string.txt_reallydelete);
alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:paddingBottom="2dip"
android:paddingTop="2dip" >
<TextView
style="@style/TextViewLarge"
android:id="@+id/fragmentlist_row_description"
android:textStyle="bold" />
</LinearLayout>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:icon="@drawable/ic_menu_add"
android:id="@+id/men_add"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_add" />
<item
android:icon="@drawable/ic_menu_preferences"
android:id="@+id/men_preferences"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_preferences" />
</menu>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/men_details"
android:title="@string/txt_details" />
<item
android:id="@+id/men_edit"
android:title="@string/txt_edit" />
<item
android:id="@+id/men_delete"
android:title="@string/txt_delete" />
</menu>
Đây là DetailsActivity:
public class ActivityDetails extends FragmentActivity implements FragmentDetails.MyDeleteListener,
FragmentDetails.MyOptionsItemSelectedListener {
private long id;
@Override
public void myDelete(final long id) {
setResult(RESULT_OK);
finish();
}
@Override
public void myOptionsItemSelected(final int action, final long id) {
if (action == R.id.men_add) {
processEdit(0);
} else if (action == R.id.men_edit) {
processEdit(id);
} else if (action == R.id.men_preferences) {
processPreferences();
}
}
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
if (requestCode == MyConstants.DLG_PREFERENCES || requestCode == MyConstants.DLG_TABLE1EDIT) {
finish();
startActivity(getIntent());
}
}
@Override
protected void onCreate(final Bundle bundle) {
super.onCreate(bundle);
if (bundle != null) {
if (bundle.containsKey("ID")) {
id = bundle.getLong("ID");
}
} else {
Bundle bundleExtras = getIntent().getExtras();
if (bundleExtras != null) {
id = bundleExtras.getLong("ID");
}
processDetails(id);
}
}
@Override
public void onSaveInstanceState(final Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putLong("ID", id);
}
private void processDetails(final long id) {
FragmentDetails fragment = new FragmentDetails(id);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(android.R.id.content, fragment);
transaction.commit();
}
private void processEdit(final long id) {
Intent intent = new Intent(this, ActivityEdit.class);
intent.putExtra("ID", id);
startActivityForResult(intent, MyConstants.DLG_TABLE1EDIT);
}
private void processPreferences() {
Intent intent = new Intent(this, MyPreferenceActivity.class);
startActivityForResult(intent, MyConstants.DLG_PREFERENCES);
}
}
Đây là DetailsFragment với Layout và Menu:
public class FragmentDetails extends Fragment {
private AlertDialog alertDialog;
private MyDeleteListener deleteListener;
private long id;
private MyOptionsItemSelectedListener optionsItemSelectedListener;
private TextView textViewDescription;
private TextView textViewId;
public FragmentDetails() {
id = 0;
}
public FragmentDetails(final long id) {
this.id = id;
}
public long getCurrentId() {
return id;
}
public interface MyDeleteListener {
public void myDelete(long id);
}
public interface MyOptionsItemSelectedListener {
public void myOptionsItemSelected(int action, long id);
}
@Override
public void onActivityCreated(final Bundle bundle) {
super.onActivityCreated(bundle);
if (bundle != null && bundle.containsKey("ID")) {
id = bundle.getLong("ID");
}
setHasOptionsMenu(true);
}
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
// Reduced
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater menuInflater) {
super.onCreateOptionsMenu(menu, menuInflater);
menu.clear();
menuInflater.inflate(R.menu.fragmentdetails, menu);
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup viewGroup, final Bundle bundle) {
View view = inflater.inflate(R.layout.fragmentdetails, null);
textViewDescription = (TextView) view.findViewById(R.id.tv_description);
textViewId = (TextView) view.findViewById(R.id.tv_id);
if (id != 0) {
Table1 table1;
if ((table1 = MyApplication.getSqliteOpenHelper().getTable1(id)) != null) {
textViewDescription.setText(Tools.defaultString(table1.getDescription()));
textViewId.setText(Tools.defaultString(String.valueOf(table1.getId())));
}
}
return view;
}
@Override
public boolean onOptionsItemSelected(final MenuItem menuItem) {
if (menuItem.getItemId() == R.id.men_delete) {
processAlertDialog(id);
return true;
} else {
optionsItemSelectedListener.myOptionsItemSelected(menuItem.getItemId(), id);
}
return super.onOptionsItemSelected(menuItem);
}
@Override
public void onSaveInstanceState(final Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putLong("ID", id);
}
private void processAlertDialog(final long id) {
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialogInterface, final int which) {
alertDialog.dismiss();
alertDialog = null;
}
});
alertDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialogInterface, final int which) {
MyApplication.getSqliteOpenHelper().deleteTable1(id);
alertDialog.dismiss();
alertDialog = null;
deleteListener.myDelete(id);
}
});
alertDialogBuilder.setCancelable(false);
alertDialogBuilder.setMessage(R.string.txt_reallydelete);
alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal" >
<TextView
style="@style/TextViewStandard"
android:layout_weight="1"
android:text="@string/txt_id" />
<TextView
style="@style/TextViewStandard"
android:id="@+id/tv_id"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal" >
<TextView
style="@style/TextViewStandard"
android:layout_weight="1"
android:text="@string/txt_description" />
<TextView
style="@style/TextViewStandard"
android:id="@+id/tv_description"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:icon="@drawable/ic_menu_add"
android:id="@+id/men_add"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_add" />
<item
android:icon="@drawable/ic_menu_edit"
android:id="@+id/men_edit"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_edit" />
<item
android:icon="@drawable/ic_menu_delete"
android:id="@+id/men_delete"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_delete" />
<item
android:icon="@drawable/ic_menu_preferences"
android:id="@+id/men_preferences"
android:showAsAction="ifRoom|withText"
android:title="@string/txt_preferences" />
</menu>
Tôi không đăng EditActivity vì nó đơn giản là một FragmentActivity mà không có một Fragment.
Đề xuất của tôi là thực hiện một việc cùng một lúc thay vì cố gắng thực hiện toàn bộ cùng một lúc. Bằng cách này, nó cũng dễ dàng hơn để kiểm tra. – Warpzit
Cảm ơn. CursorLoader đang hoạt động, thanh tác vụ gần như hoạt động (hiện tại người nghe của hai hoạt động trở nên bị sa thải khi ai đó nhấp vào thanh tác vụ vì có hoạt động bắt đầu và hoạt động điện thoại cho một thành phần phân đoạn). Vấn đề lớn nhất đối với tôi là tôi không có quyền điều hướng. Tôi rất thích hiển thị mã của tôi ở đây nhưng tôi sợ rằng mọi người sẽ không thích nhiều thứ đó. –
Nếu bạn muốn liên kết với toàn bộ dự án, hãy đặt nó trên github và cung cấp liên kết đến dự án ở đó. – Warpzit