简体   繁体   中英

Can we have multiple activities that extend CursorAdapter

I need to have more than one CursorAdapter such that each would refer to a certain fragment. However I noticed that only one CursorAdapter is working. I need to know what should be done to make both work.

PlatformCursorAdapter accesses table store

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);
}
}

and this is the RecipeCursorAdapter which accesses the recipies 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);

}
}

I noticed that the RecipeCursorAdapter is referring to the store table as well, and generating an error.

    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)

The message :-

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.

Is saying that there is no column at offset -1 in the cursor which has 2 rows and 7 columns. So offsets 0-6 would correlate to columns in the cursor.

You are getting -1 because the getColumnIndex method returns -1 when a specified column is not one of the columns in the Cursor.

eg if you had a table with columns col1, col2 and you ran a query that created Cursor c then :-

c.getColumnIndex("col1") would return an offfset of 0. c.getColumnIndex("col2") would return an offfset of 1.

whilst c.getColumnIndex("col3") would return an offfset of -1 as there is no column named col3 .

Exactly why the column name does not exist cannot be determined just from the adapter's as the likely issue is a combination of the cursor passed to the adapter and the columns being accessed within the adapter. So the code used to invoke the adapter's would be required to establish the exact cause.

As such you need to check that the Cursor's being passed to the adpaters contain the expected columns. You could do this by using the DatabaseUtils.dumpCurrentRow method in the bindView method of the adapter and then checking the output to the log.


Here's a very basic example of two fragments each with a list (StoreEntry and RecipeeEntry) but based upon some of your code.

It has a StoreEntry class as :-

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";
}

and a RecipeeEntry class as :-

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";
}

A Database helper 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);
    }
}

A very basic MainActivity, that will add some data if none exists :-

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) {
    }
}

A 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);
    }
}
  • NOTE the code in the onCreateView method and the variables defined beforehand.
  • This uses a SimpleCursorAdapter with a supplied layout.
  • processing is
    1. get the ListView according to it's id.
    2. get an instance of the DBHelper.
    3. get the cursor for this list.
    4. create the instance of the SimpleCursorAdapter using the cursor just retrieved.
    5. attach (set) the adapter to the ListView.

Here's the equivalent for the RecipeeList (basically the same) :-

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);
    }
}

result is :-

在此处输入图片说明

layouts are :-

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>

Moving On

From the above it's a short step to introduce your adapters (code as per the question), which do work.

  • Notes
    • Minor changes were made due to my use of recipee instead of recipe.
    • StoreEntry and RecipeeEntry were also amended to inlcude the _ID and CONTENT_URI constants.

For the StoreEntryFragment :-

  1. Add another class variable for the PlatformCursorAdapter :- PlatformCursorAdapter mPCA;

    So you'd have :-

     DBHelper mDBHlpr; Cursor mCsr; SimpleCursorAdapter mSCA; ListView mStoreList; PlatformCursorAdapter mPCA; //<<<< ADDED 
  2. In the onCreateViewMethod after line mStoreList.setAdapter(mSCA); and before return View add the following 2 lines :-

     mPCA = new PlatformCursorAdapter(getActivity(),mCsr); mStoreList.setAdapter(mPCA); 

For the RecipeeEntryFragment you'd have :-

    DBHelper mDBHlpr;
    Cursor mCsr;
    SimpleCursorAdapter mSCA;
    ListView mRecipeeList;
    RecipeCursorAdapter mRCA; //<<<< ADDED

and :-

    mRCA = new RecipeCursorAdapter(getActivity(),mCsr);
    mRecipeeList.setAdapter(mRCA);

Note! The following (very basic) layouts were used:-

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>

The result (only partial screen shown) is now :-

在此处输入图片说明

Apologies for the colours, not the best.

Ok finally the problem has been resolved, apparently I need to initiate a DatabaseHelper inside each CursorAdapter.

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);

    }
}
}

Thank you all for you support and time @MikeT and @pskink

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM