我们可以有多个扩展 CursorAdapter 的活动吗
Can we have multiple activities that extend CursorAdapter
我需要有多个 CursorAdapter,这样每个 CursorAdapter 都会引用某个片段。但是我注意到只有一个 CursorAdapter 在工作。我需要知道应该怎么做才能使两者都起作用。
PlatformCursorAdapter 访问 table 存储
public class PlatformCursorAdapter extends CursorAdapter {
private static final String LOG_TAG = PlatformCursorAdapter.class.getName();
public PlatformCursorAdapter(Context context, Cursor cursor){
super(context, cursor, 0);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.list_view, parent, false);
}
@Override
public void bindView(final View view, final Context context, Cursor cursor) {
//find which fields should be populated
TextView itemName = (TextView) view.findViewById(R.id.item_name);
TextView itemPrice = (TextView) view.findViewById(R.id.item_price);
final TextView itemQuantity = (TextView) view.findViewById(R.id.item_quantity);
final TextView itemWeight = view.findViewById(R.id.item_weight);
TextView supplierName = (TextView) view.findViewById(R.id.item_supplier_name);
TextView supplierNumber = (TextView) view.findViewById(R.id.item_supplier_number);
//find the columns of pets we're interested in
final String mItemName = cursor.getString(cursor.getColumnIndex(StoreEntry.COLUMN_PRODUCT_NAME));
String mItemPrice = cursor.getString(cursor.getColumnIndex(StoreEntry.COLUMN_PRODUCT_PRICE));
final String mItemQuantity = cursor.getString(cursor.getColumnIndex(StoreEntry.COLUMN_PRODUCT_QUANTITY));
final String mItemWeight = cursor.getString(cursor.getColumnIndex(StoreEntry.COLUMN_PRODUCT_WEIGHT));
String mSupplierName = cursor.getString(cursor.getColumnIndex(StoreEntry.COLUMN_SUPPLIER_NAME));
final String mSupplierNumber = cursor.getString(cursor.getColumnIndex(StoreEntry.COLUMN_SUPPLIER_NUMBER));
//get current item id
int currentId = cursor.getInt(cursor.getColumnIndex(StoreEntry._ID));
//Create the content Uri for the current Id
final Uri contentUri = Uri.withAppendedPath(StoreEntry.CONTENT_URI, Integer.toString(currentId));
//populate fields RecipeFragment
itemName.setText(mItemName);
itemPrice.setText(mItemPrice);
itemQuantity.setText(mItemQuantity);
itemWeight.setText(mItemWeight);
supplierName.setText(mSupplierName);
supplierNumber.setText(mSupplierNumber);
}
}
这是访问食谱的 RecipeCursorAdapter table
public class RecipeCursorAdapter extends CursorAdapter {
private static final String LOG_TAG = RecipeCursorAdapter.class.getName();
public RecipeCursorAdapter (Context context, Cursor cursor1){
super(context, cursor1, 0);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.recipe_activity, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
//find which fields would be populated
TextView recipeName = view.findViewById(R.id.recipe_name);
TextView recipeType = view.findViewById(R.id.recipe_type);
TextView recipeServings = view.findViewById(R.id.recipe_servings);
TextView recipeValues = view.findViewById(R.id.ingrediant_name_1);
//get the data from the table recipes
Log.e(LOG_TAG, "Number of Columns " + cursor.getColumnCount());
Log.e(LOG_TAG, "This is the Cursor Location " + cursor.getColumnIndex(RecipeEntry.COLUMN_RECIPE_SERVINGS));
String mRecipeName = cursor.getString(cursor.getColumnIndex(RecipeEntry.COLUMN_RECIPE_NAME));
String mRecipeType = cursor.getString(cursor.getColumnIndex(RecipeEntry.COLUMN_RECIPE_TYPE));
String mRecipeServings = cursor.getString(cursor.getColumnIndex(RecipeEntry.COLUMN_RECIPE_SERVINGS));
String mRecipeValues = cursor.getString(cursor.getColumnIndex(RecipeEntry.COLUMN_RECIPE_VALUES));
//get current item Id
int currenId = cursor.getInt(cursor.getColumnIndex(RecipeEntry._ID));
//create a content Uri for the current Id
final Uri contentUri = Uri.withAppendedPath(RecipeEntry.CONTENT_URI, Integer.toString(currenId));
//populate fields with their respective data
recipeName.setText(mRecipeName);
recipeType.setText(mRecipeType);
recipeServings.setText(mRecipeServings);
recipeValues.setText(mRecipeValues);
}
}
我注意到 RecipeCursorAdapter 也引用了商店 table,并生成了一个错误。
05-26 17:51:33.218 3468-3468/com.example.android.businessplatform E/com.example.android.businessplatform.RecipeCursorAdapter: Number of Columns 7
This is the Cursor Location -1
05-26 17:51:33.218 3468-3468/com.example.android.businessplatform E/CursorWindow: Failed to read row 0, column -1 from a CursorWindow which has 2 rows, 7 columns.
05-26 17:51:33.220 3468-3468/com.example.android.businessplatform E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.businessplatform, PID: 3468
java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetString(Native Method)
at android.database.CursorWindow.getString(CursorWindow.java:438)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
at android.database.CursorWrapper.getString(CursorWrapper.java:137)
at com.example.android.businessplatform.RecipeCursorAdapter.bindView(RecipeCursorAdapter.java:37)
at android.widget.CursorAdapter.getView(CursorAdapter.java:289)
at android.widget.AbsListView.obtainView(AbsListView.java:2413)
at android.widget.ListView.measureHeightOfChildren(ListView.java:1331)
at android.widget.ListView.onMeasure(ListView.java:1238)
at android.view.View.measure(View.java:19937)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
at android.view.View.measure(View.java:19937)
at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1059)
at android.view.View.measure(View.java:19937)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1632)
at android.view.View.measure(View.java:19937)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
at android.view.View.measure(View.java:19937)
at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1059)
at android.view.View.measure(View.java:19937)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6139)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:141)
at android.view.View.measure(View.java:19937)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6139)
at android.support.v7.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:400)
at android.view.View.measure(View.java:19937)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6139)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.view.View.measure(View.java:19937)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6139)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1489)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:775)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:657)
at android.view.View.measure(View.java:19937)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6139)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:729)
at android.view.View.measure(View.java:19937)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2442)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1488)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1747)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1372)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6782)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:933)
at android.view.Choreographer.doCallbacks(Choreographer.java:742)
at android.view.Choreographer.doFrame(Choreographer.java:674)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:919)
at android.os.Handler.handleCallback(Handler.java:761)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6623)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
留言:-
05-26 17:51:33.218 3468-3468/com.example.android.businessplatform E/CursorWindow: Failed to read row 0, column -1 from a CursorWindow which has 2 rows, 7 columns.
意思是2行7列游标中偏移-1处没有列。因此偏移量 0-6 将与游标中的列相关。
你得到 -1 因为 getColumnIndex
方法 returns -1 当指定列不是 Cursor 中的列之一。
例如如果你有一个 table 列 col1, col2 和你 运行 一个创建 Cursor c 的查询然后:-
c.getColumnIndex("col1")
会 return 偏移量为 0。
c.getColumnIndex("col2")
会 return 偏移量为 1。
而 c.getColumnIndex("col3")
将 return 偏移量为 -1,因为没有名为 col3.
的列
无法仅从适配器确定列名不存在的确切原因,因为可能的问题是传递给适配器的游标和在适配器中访问的列的组合。因此,需要使用用于调用适配器的代码来确定确切原因。
因此,您需要检查传递给适配器的游标是否包含预期的列。您可以通过在适配器的 bindView
方法中使用 DatabaseUtils.dumpCurrentRow
方法然后检查日志的输出来做到这一点。
这是一个非常基本的示例,其中包含两个片段,每个片段都有一个列表(StoreEntry 和 RecipeeEntry),但基于您的一些代码。
它有一个 StoreEntry class 作为 :-
public class StoreEntry {
public static final String TBNAME = "store_entry";
public static final String COLUMN_PRODUCT_NAME = "product_name";
public static final String COLUMN_PRODUCT_PRICE = "product_price";
public static final String COLUMN_PRODUCT_QUANTITY = "product_quantity";
public static final String COLUMN_PRODUCT_WEIGHT = "product_weight";
public static final String COLUMN_SUPPLIER_NAME = "supplier_name";
public static final String COLUMN_SUPPLIER_NUMBER = "supplier_number";
}
和一个 RecipeeEntry class 作为 :-
public class RecipeeEntry {
public static final String COLUMN_RECIPEE_SERVINGS = "recipee_servings";
public static final String COLUMN_RECIPEE_NAME = "recipee_name";
public static final String COLUMN_RECIPEE_TYPE = "recipee_type";
public static final String COLUMN_RECIPEE_VALUES = "recipee_values";
}
数据库助手class DBHelper :-
public class DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "mydatabase";
public static final int DBVERSION = 1;
public static final String TBSTORE = "store";
public static final String TBRECIPEE = "recipee";
private static final String store_crt = "CREATE TABLE IF NOT EXISTS " +
TBSTORE + "(" +
BaseColumns._ID + " INTEGER PRIMARY KEY, " +
StoreEntry.COLUMN_PRODUCT_NAME + " TEXT, " +
StoreEntry.COLUMN_PRODUCT_PRICE + " REAL, " +
StoreEntry.COLUMN_PRODUCT_QUANTITY + " INTEGER, " +
StoreEntry.COLUMN_PRODUCT_WEIGHT + " INTEGER, " +
StoreEntry.COLUMN_SUPPLIER_NAME + " TEXT, " +
StoreEntry.COLUMN_SUPPLIER_NUMBER + " INTEGER" +
")";
private static final String recipee_crt = "CREATE TABLE IF NOT EXISTS " +
TBRECIPEE + "(" +
BaseColumns._ID + " INTEGER PRIMARY KEY, " +
RecipeeEntry.COLUMN_RECIPEE_NAME + " TEXT, " +
RecipeeEntry.COLUMN_RECIPEE_TYPE + " TEXT, " +
RecipeeEntry.COLUMN_RECIPEE_SERVINGS + " INTEGER, " +
RecipeeEntry.COLUMN_RECIPEE_VALUES + " TEXT " +
")";
SQLiteDatabase mDB;
public DBHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(store_crt);
db.execSQL(recipee_crt);
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
}
public long addStore(String product_name,
Float product_price,
int product_quantity,
int product_weight,
String supplier_name,
int supplier_number) {
ContentValues cv = new ContentValues();
cv.put(StoreEntry.COLUMN_PRODUCT_NAME,product_name);
cv.put(StoreEntry.COLUMN_PRODUCT_PRICE,product_price);
cv.put(StoreEntry.COLUMN_PRODUCT_QUANTITY,product_quantity);
cv.put(StoreEntry.COLUMN_PRODUCT_WEIGHT,product_weight);
cv.put(StoreEntry.COLUMN_SUPPLIER_NAME,supplier_name);
cv.put(StoreEntry.COLUMN_SUPPLIER_NUMBER,supplier_number);
return mDB.insert(TBSTORE,null,cv);
}
public Cursor getStoreEntries() {
return mDB.query(TBSTORE,null,null,null,null,null,null);
}
public long addRecipee(String recipee_name, String recipee_type,int recipee_servings, String recipee_values) {
ContentValues cv = new ContentValues();
cv.put(RecipeeEntry.COLUMN_RECIPEE_NAME, recipee_name);
cv.put(RecipeeEntry.COLUMN_RECIPEE_TYPE,recipee_type);
cv.put(RecipeeEntry.COLUMN_RECIPEE_SERVINGS,recipee_servings);
cv.put(RecipeeEntry.COLUMN_RECIPEE_VALUES,recipee_values);
return mDB.insert(TBRECIPEE,null,cv);
}
public Cursor getRecipeeEntries() {
return mDB.query(TBRECIPEE,null,null,null,null,null,null);
}
}
一个非常基本的 MainActivity,如果 none 存在,它将添加一些数据:-
public class MainActivity extends AppCompatActivity
implements
StoreEntryFragment.OnFragmentInteractionListener,
RecipeeEntryFragment.OnFragmentInteractionListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DBHelper mDBHlpr = new DBHelper(this);
if (DatabaseUtils.queryNumEntries(mDBHlpr.getWritableDatabase(),DBHelper.TBSTORE) < 1) {
mDBHlpr.addStore("Rice",1.53f,10,1000,"The Rice Company",1);
mDBHlpr.addStore("Bran",2.34f,100,500,"BranDed",25);
}
if(DatabaseUtils.queryNumEntries(mDBHlpr.getWritableDatabase(),DBHelper.TBRECIPEE) < 1) {
mDBHlpr.addRecipee("RiceCrisps","Yucky",10,"This and that");
mDBHlpr.addRecipee("Bran Flakes","Makes you go",5,"Flakes or something");
}
}
@Override
public void onFragmentInteraction(Uri uri) {
}
}
一个class StoreEntryFragment :-
public class StoreEntryFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
DBHelper mDBHlpr;
Cursor mCsr;
SimpleCursorAdapter mSCA;
ListView mStoreList;
public StoreEntryFragment() {
}
public static StoreEntryFragment newInstance(String param1, String param2) {
StoreEntryFragment fragment = new StoreEntryFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_store_entry, container, false);
mStoreList = view.findViewById(R.id.store_entry_listview);
mDBHlpr = new DBHelper(getActivity());
mCsr = mDBHlpr.getStoreEntries();
mSCA = new SimpleCursorAdapter(
getActivity(),
android.R.layout.simple_list_item_2,
mCsr,
new String[]{StoreEntry.COLUMN_PRODUCT_NAME,StoreEntry.COLUMN_PRODUCT_PRICE},
new int[]{android.R.id.text1,android.R.id.text2}
);
mStoreList.setAdapter(mSCA);
return view;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
- 注意onCreateView方法中的代码和预先定义的变量。
- 这使用带有提供布局的 SimpleCursorAdapter。
- 正在处理
- 根据id获取ListView。
- 获取 DBHelper 的实例。
- 获取此列表的光标。
- 使用刚检索到的游标创建 SimpleCursorAdapter 的实例。
- 将适配器附加(设置)到 ListView。
这是 RecipeeList 的等效项(基本相同):-
public class RecipeeEntryFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
DBHelper mDBHlpr;
Cursor mCsr;
SimpleCursorAdapter mSCA;
ListView mRecipeeList;
public RecipeeEntryFragment() {
}
public static RecipeeEntryFragment newInstance(String param1, String param2) {
RecipeeEntryFragment fragment = new RecipeeEntryFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_recipee_entry, container, false);
mRecipeeList = view.findViewById(R.id.recipee_entry_listview);
mDBHlpr = new DBHelper(getActivity());
mCsr = mDBHlpr.getRecipeeEntries();
Log.d("RECIPEEFRAG","Number of rows in Cursor is " + String.valueOf(mCsr.getCount()));
mSCA = new SimpleCursorAdapter(
getActivity(),
android.R.layout.simple_list_item_2,
mCsr,
new String[]{RecipeeEntry.COLUMN_RECIPEE_NAME,RecipeeEntry.COLUMN_RECIPEE_TYPE},
new int[]{android.R.id.text1, android.R.id.text2}
);
mRecipeeList.setAdapter(mSCA);
return view;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
结果是:-
布局为:-
activity_main.xml:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp">
<fragment
android:name="flv.fragmentlistviews.StoreEntryFragment"
android:id="@+id/store_entry_fragment"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent">
</fragment>
<fragment
android:name="flv.fragmentlistviews.RecipeeEntryFragment"
android:id="@+id/recipee_entry_fragment"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent">
</fragment>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp">
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</LinearLayout>
fragment_store_entry.xml:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".StoreEntryFragment"
android:background="#AA00FF55">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="10"
android:text="@string/hello_blank_fragment" />
<ListView
android:id="@+id/store_entry_listview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="90"
android:background="#FF00EE33">
</ListView>
</LinearLayout>
fragment_recipee_entry.xml:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".RecipeeEntryFragment"
android:background="#AA0055FF">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="10"
android:text="@string/hello_blank_fragment" />
<ListView
android:id="@+id/recipee_entry_listview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="90"
android:background="#FF0033EE">
</ListView>
</LinearLayout>
继续前进
根据上面的内容,只需一小步即可介绍您的适配器(根据问题编写代码),它们确实有效。
- 备注
- 由于我使用 recipee 而不是 recipe,所以做了一些小改动。
- StoreEntry 和 RecipeeEntry 也进行了修改以包含
_ID
和 CONTENT_URI
常量。
对于 StoreEntryFragment :-
为 PlatformCursorAdapter 添加另一个 class 变量:-
PlatformCursorAdapter mPCA;
所以你会:-
DBHelper mDBHlpr;
Cursor mCsr;
SimpleCursorAdapter mSCA;
ListView mStoreList;
PlatformCursorAdapter mPCA; //<<<< ADDED
在 onCreateViewMethod
行 mStoreList.setAdapter(mSCA);
之后和 return View
之前添加以下两行:-
mPCA = new PlatformCursorAdapter(getActivity(),mCsr);
mStoreList.setAdapter(mPCA);
对于 RecipeeEntryFragment 你会有 :-
DBHelper mDBHlpr;
Cursor mCsr;
SimpleCursorAdapter mSCA;
ListView mRecipeeList;
RecipeCursorAdapter mRCA; //<<<< ADDED
和:-
mRCA = new RecipeCursorAdapter(getActivity(),mCsr);
mRecipeeList.setAdapter(mRCA);
注意!使用了以下(非常基本的)布局:-
list_view.xml:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/item_name"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/item_price"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/item_quantity"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/item_weight"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/item_supplier_name"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/item_supplier_number"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
</LinearLayout>
recipe_activity.xml:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/recipe_name"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/recipe_type"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/recipe_servings"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/ingrediant_name_1"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
</LinearLayout>
结果 (仅显示部分屏幕) 现在是:-
抱歉颜色不是最好的。
好的,问题终于解决了,显然我需要在每个 CursorAdapter 中启动一个 DatabaseHelper。
public class RecipeCursorAdapter extends CursorAdapter {
private static final String LOG_TAG = RecipeCursorAdapter.class.getName();
public RecipeCursorAdapter (Context context, Cursor cursor1){
super(context, cursor1, 0);
}
@Override
public View newView(Context context, Cursor cursor1, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.recipe_activity, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor1) {
DatabaseHelper helper = new DatabaseHelper(context);
SQLiteDatabase db = helper.getReadableDatabase();
cursor1 = db.rawQuery("SELECT * FROM " + RecipeEntry.TABLE_NAME_RECIPE, null);
Log.i(LOG_TAG, "Number of Columns " + cursor1.getColumnCount());
//find which fields would be populated
TextView recipeName = view.findViewById(R.id.recipe_name);
TextView recipeType = view.findViewById(R.id.recipe_type);
TextView recipeServings = view.findViewById(R.id.recipe_servings);
TextView recipeValues = view.findViewById(R.id.ingrediant_name_1);
if(cursor1.moveToNext()) {
//get the data from the table recipes
String mRecipeName = cursor1.getString(cursor1.getColumnIndex(RecipeEntry.COLUMN_RECIPE_NAME));
String mRecipeType = cursor1.getString(cursor1.getColumnIndexOrThrow(RecipeEntry.COLUMN_RECIPE_TYPE));
String mRecipeServings = cursor1.getString(cursor1.getColumnIndexOrThrow(RecipeEntry.COLUMN_RECIPE_SERVINGS));
String mRecipeValues = cursor1.getString(cursor1.getColumnIndexOrThrow(RecipeEntry.COLUMN_RECIPE_VALUES));
//get current item Id
int currenId = cursor1.getInt(cursor1.getColumnIndex(RecipeEntry._ID));
//create a content Uri for the current Id
final Uri contentUri = Uri.withAppendedPath(RecipeEntry.CONTENT_URI, Integer.toString(currenId));
//populate fields with their respective data
recipeName.setText(mRecipeName);
recipeType.setText(mRecipeType);
recipeServings.setText(mRecipeServings);
recipeValues.setText(mRecipeValues);
}
}
}
感谢大家的支持和时间@MikeT 和@pskink
我需要有多个 CursorAdapter,这样每个 CursorAdapter 都会引用某个片段。但是我注意到只有一个 CursorAdapter 在工作。我需要知道应该怎么做才能使两者都起作用。
PlatformCursorAdapter 访问 table 存储
public class PlatformCursorAdapter extends CursorAdapter {
private static final String LOG_TAG = PlatformCursorAdapter.class.getName();
public PlatformCursorAdapter(Context context, Cursor cursor){
super(context, cursor, 0);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.list_view, parent, false);
}
@Override
public void bindView(final View view, final Context context, Cursor cursor) {
//find which fields should be populated
TextView itemName = (TextView) view.findViewById(R.id.item_name);
TextView itemPrice = (TextView) view.findViewById(R.id.item_price);
final TextView itemQuantity = (TextView) view.findViewById(R.id.item_quantity);
final TextView itemWeight = view.findViewById(R.id.item_weight);
TextView supplierName = (TextView) view.findViewById(R.id.item_supplier_name);
TextView supplierNumber = (TextView) view.findViewById(R.id.item_supplier_number);
//find the columns of pets we're interested in
final String mItemName = cursor.getString(cursor.getColumnIndex(StoreEntry.COLUMN_PRODUCT_NAME));
String mItemPrice = cursor.getString(cursor.getColumnIndex(StoreEntry.COLUMN_PRODUCT_PRICE));
final String mItemQuantity = cursor.getString(cursor.getColumnIndex(StoreEntry.COLUMN_PRODUCT_QUANTITY));
final String mItemWeight = cursor.getString(cursor.getColumnIndex(StoreEntry.COLUMN_PRODUCT_WEIGHT));
String mSupplierName = cursor.getString(cursor.getColumnIndex(StoreEntry.COLUMN_SUPPLIER_NAME));
final String mSupplierNumber = cursor.getString(cursor.getColumnIndex(StoreEntry.COLUMN_SUPPLIER_NUMBER));
//get current item id
int currentId = cursor.getInt(cursor.getColumnIndex(StoreEntry._ID));
//Create the content Uri for the current Id
final Uri contentUri = Uri.withAppendedPath(StoreEntry.CONTENT_URI, Integer.toString(currentId));
//populate fields RecipeFragment
itemName.setText(mItemName);
itemPrice.setText(mItemPrice);
itemQuantity.setText(mItemQuantity);
itemWeight.setText(mItemWeight);
supplierName.setText(mSupplierName);
supplierNumber.setText(mSupplierNumber);
}
}
这是访问食谱的 RecipeCursorAdapter table
public class RecipeCursorAdapter extends CursorAdapter {
private static final String LOG_TAG = RecipeCursorAdapter.class.getName();
public RecipeCursorAdapter (Context context, Cursor cursor1){
super(context, cursor1, 0);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.recipe_activity, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
//find which fields would be populated
TextView recipeName = view.findViewById(R.id.recipe_name);
TextView recipeType = view.findViewById(R.id.recipe_type);
TextView recipeServings = view.findViewById(R.id.recipe_servings);
TextView recipeValues = view.findViewById(R.id.ingrediant_name_1);
//get the data from the table recipes
Log.e(LOG_TAG, "Number of Columns " + cursor.getColumnCount());
Log.e(LOG_TAG, "This is the Cursor Location " + cursor.getColumnIndex(RecipeEntry.COLUMN_RECIPE_SERVINGS));
String mRecipeName = cursor.getString(cursor.getColumnIndex(RecipeEntry.COLUMN_RECIPE_NAME));
String mRecipeType = cursor.getString(cursor.getColumnIndex(RecipeEntry.COLUMN_RECIPE_TYPE));
String mRecipeServings = cursor.getString(cursor.getColumnIndex(RecipeEntry.COLUMN_RECIPE_SERVINGS));
String mRecipeValues = cursor.getString(cursor.getColumnIndex(RecipeEntry.COLUMN_RECIPE_VALUES));
//get current item Id
int currenId = cursor.getInt(cursor.getColumnIndex(RecipeEntry._ID));
//create a content Uri for the current Id
final Uri contentUri = Uri.withAppendedPath(RecipeEntry.CONTENT_URI, Integer.toString(currenId));
//populate fields with their respective data
recipeName.setText(mRecipeName);
recipeType.setText(mRecipeType);
recipeServings.setText(mRecipeServings);
recipeValues.setText(mRecipeValues);
}
}
我注意到 RecipeCursorAdapter 也引用了商店 table,并生成了一个错误。
05-26 17:51:33.218 3468-3468/com.example.android.businessplatform E/com.example.android.businessplatform.RecipeCursorAdapter: Number of Columns 7
This is the Cursor Location -1
05-26 17:51:33.218 3468-3468/com.example.android.businessplatform E/CursorWindow: Failed to read row 0, column -1 from a CursorWindow which has 2 rows, 7 columns.
05-26 17:51:33.220 3468-3468/com.example.android.businessplatform E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.businessplatform, PID: 3468
java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetString(Native Method)
at android.database.CursorWindow.getString(CursorWindow.java:438)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
at android.database.CursorWrapper.getString(CursorWrapper.java:137)
at com.example.android.businessplatform.RecipeCursorAdapter.bindView(RecipeCursorAdapter.java:37)
at android.widget.CursorAdapter.getView(CursorAdapter.java:289)
at android.widget.AbsListView.obtainView(AbsListView.java:2413)
at android.widget.ListView.measureHeightOfChildren(ListView.java:1331)
at android.widget.ListView.onMeasure(ListView.java:1238)
at android.view.View.measure(View.java:19937)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
at android.view.View.measure(View.java:19937)
at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1059)
at android.view.View.measure(View.java:19937)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1632)
at android.view.View.measure(View.java:19937)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
at android.view.View.measure(View.java:19937)
at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1059)
at android.view.View.measure(View.java:19937)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6139)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:141)
at android.view.View.measure(View.java:19937)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6139)
at android.support.v7.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:400)
at android.view.View.measure(View.java:19937)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6139)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.view.View.measure(View.java:19937)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6139)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1489)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:775)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:657)
at android.view.View.measure(View.java:19937)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6139)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:729)
at android.view.View.measure(View.java:19937)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2442)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1488)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1747)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1372)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6782)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:933)
at android.view.Choreographer.doCallbacks(Choreographer.java:742)
at android.view.Choreographer.doFrame(Choreographer.java:674)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:919)
at android.os.Handler.handleCallback(Handler.java:761)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6623)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
留言:-
05-26 17:51:33.218 3468-3468/com.example.android.businessplatform E/CursorWindow: Failed to read row 0, column -1 from a CursorWindow which has 2 rows, 7 columns.
意思是2行7列游标中偏移-1处没有列。因此偏移量 0-6 将与游标中的列相关。
你得到 -1 因为 getColumnIndex
方法 returns -1 当指定列不是 Cursor 中的列之一。
例如如果你有一个 table 列 col1, col2 和你 运行 一个创建 Cursor c 的查询然后:-
c.getColumnIndex("col1")
会 return 偏移量为 0。
c.getColumnIndex("col2")
会 return 偏移量为 1。
而 c.getColumnIndex("col3")
将 return 偏移量为 -1,因为没有名为 col3.
无法仅从适配器确定列名不存在的确切原因,因为可能的问题是传递给适配器的游标和在适配器中访问的列的组合。因此,需要使用用于调用适配器的代码来确定确切原因。
因此,您需要检查传递给适配器的游标是否包含预期的列。您可以通过在适配器的 bindView
方法中使用 DatabaseUtils.dumpCurrentRow
方法然后检查日志的输出来做到这一点。
这是一个非常基本的示例,其中包含两个片段,每个片段都有一个列表(StoreEntry 和 RecipeeEntry),但基于您的一些代码。
它有一个 StoreEntry class 作为 :-
public class StoreEntry {
public static final String TBNAME = "store_entry";
public static final String COLUMN_PRODUCT_NAME = "product_name";
public static final String COLUMN_PRODUCT_PRICE = "product_price";
public static final String COLUMN_PRODUCT_QUANTITY = "product_quantity";
public static final String COLUMN_PRODUCT_WEIGHT = "product_weight";
public static final String COLUMN_SUPPLIER_NAME = "supplier_name";
public static final String COLUMN_SUPPLIER_NUMBER = "supplier_number";
}
和一个 RecipeeEntry class 作为 :-
public class RecipeeEntry {
public static final String COLUMN_RECIPEE_SERVINGS = "recipee_servings";
public static final String COLUMN_RECIPEE_NAME = "recipee_name";
public static final String COLUMN_RECIPEE_TYPE = "recipee_type";
public static final String COLUMN_RECIPEE_VALUES = "recipee_values";
}
数据库助手class DBHelper :-
public class DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "mydatabase";
public static final int DBVERSION = 1;
public static final String TBSTORE = "store";
public static final String TBRECIPEE = "recipee";
private static final String store_crt = "CREATE TABLE IF NOT EXISTS " +
TBSTORE + "(" +
BaseColumns._ID + " INTEGER PRIMARY KEY, " +
StoreEntry.COLUMN_PRODUCT_NAME + " TEXT, " +
StoreEntry.COLUMN_PRODUCT_PRICE + " REAL, " +
StoreEntry.COLUMN_PRODUCT_QUANTITY + " INTEGER, " +
StoreEntry.COLUMN_PRODUCT_WEIGHT + " INTEGER, " +
StoreEntry.COLUMN_SUPPLIER_NAME + " TEXT, " +
StoreEntry.COLUMN_SUPPLIER_NUMBER + " INTEGER" +
")";
private static final String recipee_crt = "CREATE TABLE IF NOT EXISTS " +
TBRECIPEE + "(" +
BaseColumns._ID + " INTEGER PRIMARY KEY, " +
RecipeeEntry.COLUMN_RECIPEE_NAME + " TEXT, " +
RecipeeEntry.COLUMN_RECIPEE_TYPE + " TEXT, " +
RecipeeEntry.COLUMN_RECIPEE_SERVINGS + " INTEGER, " +
RecipeeEntry.COLUMN_RECIPEE_VALUES + " TEXT " +
")";
SQLiteDatabase mDB;
public DBHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(store_crt);
db.execSQL(recipee_crt);
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
}
public long addStore(String product_name,
Float product_price,
int product_quantity,
int product_weight,
String supplier_name,
int supplier_number) {
ContentValues cv = new ContentValues();
cv.put(StoreEntry.COLUMN_PRODUCT_NAME,product_name);
cv.put(StoreEntry.COLUMN_PRODUCT_PRICE,product_price);
cv.put(StoreEntry.COLUMN_PRODUCT_QUANTITY,product_quantity);
cv.put(StoreEntry.COLUMN_PRODUCT_WEIGHT,product_weight);
cv.put(StoreEntry.COLUMN_SUPPLIER_NAME,supplier_name);
cv.put(StoreEntry.COLUMN_SUPPLIER_NUMBER,supplier_number);
return mDB.insert(TBSTORE,null,cv);
}
public Cursor getStoreEntries() {
return mDB.query(TBSTORE,null,null,null,null,null,null);
}
public long addRecipee(String recipee_name, String recipee_type,int recipee_servings, String recipee_values) {
ContentValues cv = new ContentValues();
cv.put(RecipeeEntry.COLUMN_RECIPEE_NAME, recipee_name);
cv.put(RecipeeEntry.COLUMN_RECIPEE_TYPE,recipee_type);
cv.put(RecipeeEntry.COLUMN_RECIPEE_SERVINGS,recipee_servings);
cv.put(RecipeeEntry.COLUMN_RECIPEE_VALUES,recipee_values);
return mDB.insert(TBRECIPEE,null,cv);
}
public Cursor getRecipeeEntries() {
return mDB.query(TBRECIPEE,null,null,null,null,null,null);
}
}
一个非常基本的 MainActivity,如果 none 存在,它将添加一些数据:-
public class MainActivity extends AppCompatActivity
implements
StoreEntryFragment.OnFragmentInteractionListener,
RecipeeEntryFragment.OnFragmentInteractionListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DBHelper mDBHlpr = new DBHelper(this);
if (DatabaseUtils.queryNumEntries(mDBHlpr.getWritableDatabase(),DBHelper.TBSTORE) < 1) {
mDBHlpr.addStore("Rice",1.53f,10,1000,"The Rice Company",1);
mDBHlpr.addStore("Bran",2.34f,100,500,"BranDed",25);
}
if(DatabaseUtils.queryNumEntries(mDBHlpr.getWritableDatabase(),DBHelper.TBRECIPEE) < 1) {
mDBHlpr.addRecipee("RiceCrisps","Yucky",10,"This and that");
mDBHlpr.addRecipee("Bran Flakes","Makes you go",5,"Flakes or something");
}
}
@Override
public void onFragmentInteraction(Uri uri) {
}
}
一个class StoreEntryFragment :-
public class StoreEntryFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
DBHelper mDBHlpr;
Cursor mCsr;
SimpleCursorAdapter mSCA;
ListView mStoreList;
public StoreEntryFragment() {
}
public static StoreEntryFragment newInstance(String param1, String param2) {
StoreEntryFragment fragment = new StoreEntryFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_store_entry, container, false);
mStoreList = view.findViewById(R.id.store_entry_listview);
mDBHlpr = new DBHelper(getActivity());
mCsr = mDBHlpr.getStoreEntries();
mSCA = new SimpleCursorAdapter(
getActivity(),
android.R.layout.simple_list_item_2,
mCsr,
new String[]{StoreEntry.COLUMN_PRODUCT_NAME,StoreEntry.COLUMN_PRODUCT_PRICE},
new int[]{android.R.id.text1,android.R.id.text2}
);
mStoreList.setAdapter(mSCA);
return view;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
- 注意onCreateView方法中的代码和预先定义的变量。
- 这使用带有提供布局的 SimpleCursorAdapter。
- 正在处理
- 根据id获取ListView。
- 获取 DBHelper 的实例。
- 获取此列表的光标。
- 使用刚检索到的游标创建 SimpleCursorAdapter 的实例。
- 将适配器附加(设置)到 ListView。
这是 RecipeeList 的等效项(基本相同):-
public class RecipeeEntryFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
DBHelper mDBHlpr;
Cursor mCsr;
SimpleCursorAdapter mSCA;
ListView mRecipeeList;
public RecipeeEntryFragment() {
}
public static RecipeeEntryFragment newInstance(String param1, String param2) {
RecipeeEntryFragment fragment = new RecipeeEntryFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_recipee_entry, container, false);
mRecipeeList = view.findViewById(R.id.recipee_entry_listview);
mDBHlpr = new DBHelper(getActivity());
mCsr = mDBHlpr.getRecipeeEntries();
Log.d("RECIPEEFRAG","Number of rows in Cursor is " + String.valueOf(mCsr.getCount()));
mSCA = new SimpleCursorAdapter(
getActivity(),
android.R.layout.simple_list_item_2,
mCsr,
new String[]{RecipeeEntry.COLUMN_RECIPEE_NAME,RecipeeEntry.COLUMN_RECIPEE_TYPE},
new int[]{android.R.id.text1, android.R.id.text2}
);
mRecipeeList.setAdapter(mSCA);
return view;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
结果是:-
布局为:-
activity_main.xml:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp">
<fragment
android:name="flv.fragmentlistviews.StoreEntryFragment"
android:id="@+id/store_entry_fragment"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent">
</fragment>
<fragment
android:name="flv.fragmentlistviews.RecipeeEntryFragment"
android:id="@+id/recipee_entry_fragment"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent">
</fragment>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp">
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</LinearLayout>
fragment_store_entry.xml:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".StoreEntryFragment"
android:background="#AA00FF55">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="10"
android:text="@string/hello_blank_fragment" />
<ListView
android:id="@+id/store_entry_listview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="90"
android:background="#FF00EE33">
</ListView>
</LinearLayout>
fragment_recipee_entry.xml:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".RecipeeEntryFragment"
android:background="#AA0055FF">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="10"
android:text="@string/hello_blank_fragment" />
<ListView
android:id="@+id/recipee_entry_listview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="90"
android:background="#FF0033EE">
</ListView>
</LinearLayout>
继续前进
根据上面的内容,只需一小步即可介绍您的适配器(根据问题编写代码),它们确实有效。
- 备注
- 由于我使用 recipee 而不是 recipe,所以做了一些小改动。
- StoreEntry 和 RecipeeEntry 也进行了修改以包含
_ID
和CONTENT_URI
常量。
对于 StoreEntryFragment :-
为 PlatformCursorAdapter 添加另一个 class 变量:- PlatformCursorAdapter mPCA;
所以你会:-
DBHelper mDBHlpr; Cursor mCsr; SimpleCursorAdapter mSCA; ListView mStoreList; PlatformCursorAdapter mPCA; //<<<< ADDED
在
onCreateViewMethod
行mStoreList.setAdapter(mSCA);
之后和return View
之前添加以下两行:-mPCA = new PlatformCursorAdapter(getActivity(),mCsr); mStoreList.setAdapter(mPCA);
对于 RecipeeEntryFragment 你会有 :-
DBHelper mDBHlpr;
Cursor mCsr;
SimpleCursorAdapter mSCA;
ListView mRecipeeList;
RecipeCursorAdapter mRCA; //<<<< ADDED
和:-
mRCA = new RecipeCursorAdapter(getActivity(),mCsr);
mRecipeeList.setAdapter(mRCA);
注意!使用了以下(非常基本的)布局:-
list_view.xml:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/item_name"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/item_price"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/item_quantity"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/item_weight"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/item_supplier_name"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/item_supplier_number"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
</LinearLayout>
recipe_activity.xml:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/recipe_name"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/recipe_type"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/recipe_servings"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<TextView
android:id="@+id/ingrediant_name_1"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
</LinearLayout>
结果 (仅显示部分屏幕) 现在是:-
抱歉颜色不是最好的。
好的,问题终于解决了,显然我需要在每个 CursorAdapter 中启动一个 DatabaseHelper。
public class RecipeCursorAdapter extends CursorAdapter {
private static final String LOG_TAG = RecipeCursorAdapter.class.getName();
public RecipeCursorAdapter (Context context, Cursor cursor1){
super(context, cursor1, 0);
}
@Override
public View newView(Context context, Cursor cursor1, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.recipe_activity, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor1) {
DatabaseHelper helper = new DatabaseHelper(context);
SQLiteDatabase db = helper.getReadableDatabase();
cursor1 = db.rawQuery("SELECT * FROM " + RecipeEntry.TABLE_NAME_RECIPE, null);
Log.i(LOG_TAG, "Number of Columns " + cursor1.getColumnCount());
//find which fields would be populated
TextView recipeName = view.findViewById(R.id.recipe_name);
TextView recipeType = view.findViewById(R.id.recipe_type);
TextView recipeServings = view.findViewById(R.id.recipe_servings);
TextView recipeValues = view.findViewById(R.id.ingrediant_name_1);
if(cursor1.moveToNext()) {
//get the data from the table recipes
String mRecipeName = cursor1.getString(cursor1.getColumnIndex(RecipeEntry.COLUMN_RECIPE_NAME));
String mRecipeType = cursor1.getString(cursor1.getColumnIndexOrThrow(RecipeEntry.COLUMN_RECIPE_TYPE));
String mRecipeServings = cursor1.getString(cursor1.getColumnIndexOrThrow(RecipeEntry.COLUMN_RECIPE_SERVINGS));
String mRecipeValues = cursor1.getString(cursor1.getColumnIndexOrThrow(RecipeEntry.COLUMN_RECIPE_VALUES));
//get current item Id
int currenId = cursor1.getInt(cursor1.getColumnIndex(RecipeEntry._ID));
//create a content Uri for the current Id
final Uri contentUri = Uri.withAppendedPath(RecipeEntry.CONTENT_URI, Integer.toString(currenId));
//populate fields with their respective data
recipeName.setText(mRecipeName);
recipeType.setText(mRecipeType);
recipeServings.setText(mRecipeServings);
recipeValues.setText(mRecipeValues);
}
}
}
感谢大家的支持和时间@MikeT 和@pskink