使用 CursorAdapter Sunclass 进行应用程序粉碎

问题描述 投票:0回答:1

当我单击应该让我进入此列表视图活动的项目时,应用程序崩溃了,我不知道我做错了什么,也不知道我需要做什么来纠正它。这是我的 CursorAdapter 子类,用于显示列表视图:

package com.example.marhbabikapp;
import android.content.Context;import android.database.Cursor;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.CursorAdapter;import android.widget.ImageView;import android.widget.TextView;
import com.bumptech.glide.Glide;
public class DestinationCursorAdapter extends CursorAdapter {MyDBHandler myDBHandler;
public DestinationCursorAdapter(Context context, Cursor cursor,int flags ,MyDBHandler dbHandler) {
    super(context, cursor, flags);
    this.myDBHandler = dbHandler;;
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    return LayoutInflater.from(context).inflate(R.layout.item_destinationtype, parent, false);
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
    TextView nameTextView = view.findViewById(R.id.destinationTextViewName);
    TextView descriptionTextView = view.findViewById(R.id.destinationTextViewDescription);
    ImageView imageView = view.findViewById(R.id.destinationImageView);

    String name = cursor.getString(cursor.getColumnIndexOrThrow(MyDBHandler.DESTINATION_NAME));
    String description = cursor.getString(cursor.getColumnIndexOrThrow(MyDBHandler.DESTINATION_DESCRIPTION));
    String imageUrl = cursor.getString(cursor.getColumnIndexOrThrow(MyDBHandler.PHOTO_URL));

    nameTextView.setText(name);
    descriptionTextView.setText(description);

    Glide.with(context)
            .load(imageUrl)
            //.placeholder(R.drawable.placeholder_image) // Placeholder image while loading
            //.error(R.drawable.error_image) // Error image if Glide fails to load
            .into(imageView);
}
}

这是我尝试放置列表视图时的 types_screen 活动:

包 com.example.marhbabikapp;

import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;import android.content.Intent;import android.database.Cursor;import android.os.Bundle;import android.widget.ListView;import android.widget.TextView;import android.widget.Toast;
import java.util.Locale;
public class Types_screen extends AppCompatActivity {
private ListView mylistView;
private MyDBHandler dbHandler;
private DestinationCursorAdapter destinationCursorAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_types_screen);

    Intent intent = getIntent();
    String type = intent.getStringExtra("DESTINATION_TYPE");

    mylistView = findViewById(R.id.listViewDestinations);
    dbHandler = new MyDBHandler(this);

    Cursor cursor = null;

    if ("Historical".equals(type.trim())) {
        cursor = dbHandler.getHistoricalDestinationsCursor();
    } else if ("Natural".equals(type.trim())) {
        cursor = dbHandler.getNaturalDestinationsCursor();
    } else if ("Coastal".equals(type.trim())) {
        cursor = dbHandler.getCoastalDestinationsCursor();
    } else if ("Modern".equals(type.trim())) {
        cursor = dbHandler.getModernDestinationsCursor();
    } else if ("Cultural".equals(type.trim())) {
        cursor = dbHandler.getCulturalDestinationsCursor();
    } else if ("Saharian".equals(type.trim())) {
        cursor = dbHandler.getSaharianDestinationsCursor();
    } else if ("Snowy".equals(type.trim())) {
        cursor = dbHandler.getSnowyDestinationsCursor();
    }

        destinationCursorAdapter = new DestinationCursorAdapter(this, cursor, 0, dbHandler);
        mylistView.setAdapter(destinationCursorAdapter);

}

}

这是这些方法的一个实例: 公共光标 getSnowyDestinationsCursor() { SQLiteDatabase db = this.getReadableDatabase();

    String[] projection = {
            DESTINATION_NAME,
            DESTINATION_DESCRIPTION,
            PHOTO_URL,
            REGION
    };

    String selection = SNOWY + " = ?";
    String[] selectionArgs = { "1" };

    return db.query(
            TABLE_DESTINATIONS,
            projection,
            selection,
            selectionArgs,
            null,
            null,
            null
    );
}
  1. 我尝试创建另一个光标适配器子类,但没有改变任何东西
java android kotlin android-studio android-sqlite
1个回答
0
投票

毫无疑问,但不能消除其他问题,您错过了 CursorAdapterCRUCIAL 方面。

> 光标必须包含名为“_id”的列,否则此类将无法工作。

没有明确解释的是,该列应该是唯一标识单行的整数(长)值。通常隐藏的 rowid (对于普通表)符合这些要求。

  • 事实上,假设使用 rowid 列或 rowid 列的别名。
    • 如果列定义是
      the_column_name_often_id_or_underscore_id INTEGER PRIMARY KEY 
      (有或没有
      AUTOINCREMENT
      (如果实际上不需要,那就浪费了)
      • 注意完全正确
        INTEGER
        (与大小写无关)任何其他内容,例如
        INT

假设有一个普通表(例如,不是没有 ROWID 或虚拟表),可以使用以下快速修复:-

    String[] projection = {
            "rowid AS " + BaseColumns._ID, /*<<<<<<<<<< ADDED */
            DESTINATION_NAME,
            DESTINATION_DESCRIPTION,
            PHOTO_URL,
            REGION
    };  

这将克服引发的非法参数异常(假设代码到目前为止)。

问题演示

演示如何使用您的代码(做出许多假设),然后:-

2024-01-31 12:18:35.343 2228-2228/a.a.so77904630cursdoradapter D/AndroidRuntime: Shutting down VM
    
    
    --------- beginning of crash
2024-01-31 12:18:35.344 2228-2228/a.a.so77904630cursdoradapter E/AndroidRuntime: FATAL EXCEPTION: main
    Process: a.a.so77904630cursdoradapter, PID: 2228
    java.lang.RuntimeException: Unable to start activity ComponentInfo{a.a.so77904630cursdoradapter/a.a.so77904630cursdoradapter.MainActivity}: java.lang.IllegalArgumentException: column '_id' does not exist. Available columns: [destination_name, destination_description, photo_url, region]
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.IllegalArgumentException: column '_id' does not exist. Available columns: [destination_name, destination_description, photo_url, region]
        at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:340)
        at android.widget.CursorAdapter.init(CursorAdapter.java:180)
        at android.widget.CursorAdapter.<init>(CursorAdapter.java:157)
        at a.a.so77904630cursdoradapter.DestinationCursorAdapter.<init>(DestinationCursorAdapter.java:14)
        at a.a.so77904630cursdoradapter.MainActivity.setOrRefreshListView(MainActivity.java:56)
        at a.a.so77904630cursdoradapter.MainActivity.onCreate(MainActivity.java:28)
  • 即Destination CursorAdapter的第14行是发生异常的地方,也就是

    super(context, cursor, flags);

  • 这条信息非常清楚。

已修复

只需更改为使用:-

    String[] projection = {
            "rowid AS " + BaseColumns._ID, /* ADDED */
            DESTINATION_NAME,
            DESTINATION_DESCRIPTION,
            PHOTO_URL,
            REGION
    };

然后:-

  • 显然您的显示可能会有所不同。使用的应用程序是基于可用代码的模型,因此假设了其他代码(例如布局)。可以看出,ListView 显示一行(这是作为 MyDatabaseHandler 的
    onCreate
    方法的一部分插入的)。
© www.soinside.com 2019 - 2024. All rights reserved.