Сообщение: -
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.
Говорит, что в курсоре нет столбца со смещением -1, в котором есть 2 строки и 7 столбцов.Таким образом, смещения 0-6 будут соответствовать столбцам в курсоре.
Вы получаете -1 , потому что метод getColumnIndex
возвращает -1 , когда указанный столбецни один из столбцов в Курсоре.
Например, если у вас есть таблица со столбцами col1, col2 и вы выполнили запрос, который создал Cursor c, то: -
c.getColumnIndex("col1")
вернетЗначение offfset, равное 0. c.getColumnIndex("col2")
вернет значение offfset, равное 1.
, тогда как c.getColumnIndex("col3")
вернет значение offfset, равное -1, поскольку столбец с именем col3 .
* 1023 отсутствует.* Точно, почему имя столбца не существует, не может быть определено только от адаптера, поскольку вероятная проблема - комбинация курсора, переданного адаптеру, и столбцов, к которым обращаются в адаптере.Таким образом, код, используемый для вызова адаптера, потребуется для установления точной причины.
Таким образом, вам необходимо проверить, что курсор, передаваемый в adpaters, содержит ожидаемые столбцы.Вы можете сделать это, используя метод DatabaseUtils.dumpCurrentRow
в методе bindView
адаптера и затем проверяя вывод в журнал.
Вот очень простой пример двух фрагментов, каждый со списком(StoreEntry и RecipeeEntry), но на основе некоторого вашего кода.
Он имеет класс StoreEntry как: -
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 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 Вспомогательный класс базы данных 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, которая добавит некоторые данные, если их не существует:-
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) {
}
}
Класс 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с предоставленным макетом.
- обработка составляет
- получить ListView в соответствии с его идентификатором.
- получить экземпляр DBHelper.
- получить курсор дляэтот список.
- создайте экземпляр SimpleCursorAdapter, используя cursили только что извлеченный.
- присоедините (установите) адаптер к 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>
frag_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>
frag_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>
Двигаясь дальше
Из вышеперечисленного можно быстро представить свои адаптеры (код согласно вопросу), которые работают.
- Примечания
- Незначительныеизменения были сделаны из-за моего использования рецепта вместо рецепта.
- StoreEntry и RecipeeEntry были также изменены, чтобы включить константы
_ID
и CONTENT_URI
.
Для StoreEntryFragment : -
Добавьте еще одну переменную класса для PlatformCursorAdapter: - PlatformCursorAdapter mPCA;
Таким образом, вы получите: -
DBHelper mDBHlpr;
Cursor mCsr;
SimpleCursorAdapter mSCA;
ListView mStoreList;
PlatformCursorAdapter mPCA; //<<<< ADDED
В onCreateViewMethod
после строки mStoreList.setAdapter(mSCA);
и до return View
добавьте следующие 2 строки: -
mPCA = new PlatformCursorAdapter(getActivity(),mCsr);
mStoreList.setAdapter(mPCA);
Для RecipeeEntryFragment you 'd иметь: -
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>
Результат (показан только частичный экран) теперь: -
Извиненияне самые лучшие цвета.