RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 611847
Accepted
Вероника
Вероника
Asked:2020-01-07 19:03:26 +0000 UTC2020-01-07 19:03:26 +0000 UTC 2020-01-07 19:03:26 +0000 UTC

通过 SimpleCursorAdapter 添加到 ListView

  • 772

我正在制作一个从俄语到英语的字典程序,反之亦然。

有一个表格Spinner可以选择翻译方向。有一个txtSearch用于搜索单词的文本字段,并且ListView根据翻译方向显示数据库表中的单词。ListView我通过基于SimpleCursorAdapter.

这是适配器代码:

public class MyCursorAdapter extends SimpleCursorAdapter {
    private int layout;
    DBHeler db;
    Context ctx;

    MyCursorAdapter(Context ctx, int layout, Cursor cursor, String[] from, int[] to, DBHeler db) {
        super(ctx, layout, cursor, from, to);
        this.layout = layout;
        this.db = db;
        this.ctx = ctx;
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(layout, parent, false);
        return view;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {

        String bukva = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_SLOVO)).substring(0, 1).toUpperCase();
        final String slovo = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_SLOVO));
        final String izbrannoe = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_IZBRANNOE));

        TextView txtBukva = (TextView) view.findViewById(R.id.txtBukva);
        TextView txtSlovo = (TextView) view.findViewById(R.id.txtSlovo);
        final ImageButton btnIzbrannoe = (ImageButton) view.findViewById(R.id.btnIzbrannoe);

        txtBukva.setText(bukva);
        txtSlovo.setText(slovo);
        btnIzbrannoe.setFocusable(false);

        if (izbrannoe.equals("1")) {
            btnIzbrannoe.setImageResource(R.drawable.icon_star_yellow);
        } else if (izbrannoe.equals("0")) {
            btnIzbrannoe.setImageResource(R.drawable.icon_star_outline_black);
        }

        btnIzbrannoe.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (izbrannoe.equals("1")) {
                    ContentValues values = new ContentValues();
                    values.put(Contract.Entry.COLUMN_IZBRANNOE, "0");
                    long newRowId = db.database.update(Contract.Entry.TABLE_RUEN, values, Contract.Entry.COLUMN_SLOVO + "= ?", new String[]{slovo});
                    if (newRowId == -1) {
                        Toast.makeText(ctx, "Ошибка", Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(ctx, "Удалено из избранное", Toast.LENGTH_SHORT).show();
                        btnIzbrannoe.setImageResource(R.drawable.icon_star_outline_black);
                    }
                } else if (izbrannoe.equals("0")) {
                    ContentValues values = new ContentValues();
                    values.put(Contract.Entry.COLUMN_IZBRANNOE, "1");
                    long newRowId = db.database.update(Contract.Entry.TABLE_RUEN, values, Contract.Entry.COLUMN_SLOVO + "= ?", new String[]{slovo});
                    if (newRowId == -1) {
                        Toast.makeText(ctx, "Ошибка", Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(ctx, "Добавлено в избранное", Toast.LENGTH_SHORT).show();
                        btnIzbrannoe.setImageResource(R.drawable.icon_star_yellow);
                    }
                }
            }
        });
    }
}

这是 MainActivity 的主要代码:

public class MainActivity extends AppCompatActivity {

    private AutoCompleteTextView txtSearch;
    private Spinner spinner;
    private ListView list;
    private ImageButton btnClear;

    DBHeler db;

    private MyCursorAdapter myCursorAdapter;
    private Cursor cursor;
    String[] from;
    int[] to;

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

        db = new DBHeler(this);

        try {
            db.createDataBase();
            db.openDataBase();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        spinner = (Spinner) findViewById(R.id.spinner);
        // Настраиваем адаптер
        ArrayAdapter<?> adapter =
                ArrayAdapter.createFromResource(this, R.array.types, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        // Вызываем адаптер
        spinner.setAdapter(adapter);

        txtSearch = (AutoCompleteTextView) findViewById(R.id.txtSearch);
        list = (ListView) findViewById(R.id.list);
        btnClear = (ImageButton) findViewById(R.id.btnClear);

        /*Выводим в список все слова, при запуске программы*/
        String selectedItem = spinner.getSelectedItem().toString();

        if (selectedItem.equals("С русского на английский")) {
            cursor = db.getRuWords();
            from = new String[] {Contract.Entry.COLUMN_SLOVO, Contract.Entry.COLUMN_SLOVO, Contract.Entry.COLUMN_IZBRANNOE};
            to = new int[] {R.id.txtBukva, R.id.txtSlovo, R.id.btnIzbrannoe};
            myCursorAdapter = new MyCursorAdapter(this, R.layout.item, cursor, from, to, db);
            list.setAdapter(myCursorAdapter);
        } else if (selectedItem.equals("С английского на русский")) {
            cursor = db.getEnWords();
            from = new String[] {Contract.Entry.COLUMN_SLOVO, Contract.Entry.COLUMN_SLOVO, Contract.Entry.COLUMN_IZBRANNOE};
            to = new int[] {R.id.txtBukva, R.id.txtSlovo, R.id.btnIzbrannoe};
            myCursorAdapter = new MyCursorAdapter(this, R.layout.item, cursor, from, to, db);
            list.setAdapter(myCursorAdapter);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        txtSearch.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean b) {
                if (b && txtSearch.getText().toString().length() > 0)
                    btnClear.setVisibility(View.VISIBLE);
                else
                    btnClear.setVisibility(View.INVISIBLE);
            }
        });

        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Intent intent = new Intent(MainActivity.this, SlovoActivity.class);
                CharSequence strCharSequence = ((TextView)view.findViewById(R.id.txtSlovo)).getText();
                String str = strCharSequence.toString().toLowerCase().trim();
                String selectedItem = spinner.getSelectedItem().toString();
                if (selectedItem.equals("С русского на английский")) {
                    intent.putExtra("slovo", str);
                    intent.putExtra("type", "RU");
                    startActivity(intent);
                } else if (selectedItem.equals("С английского на русский")) {
                    intent.putExtra("slovo", str);
                    intent.putExtra("type", "EN");
                    startActivity(intent);
                }
            }
        });

        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                txtSearch.setText("");
                String str = adapterView.getItemAtPosition(i).toString();
                if (str.equals("С русского на английский")) {
                    cursor = db.getRuWords();
                    myCursorAdapter = new MyCursorAdapter(MainActivity.this, R.layout.item, cursor, from, to, db);
                    list.setAdapter(myCursorAdapter);
                } else if (str.equals("С английского на русский")) {
                    cursor = db.getEnWords();
                    myCursorAdapter = new MyCursorAdapter(MainActivity.this, R.layout.item, cursor, from, to, db);
                    list.setAdapter(myCursorAdapter);
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });
    }
}

下面是连接数据库、查询游标数据等类代码:

public class Contract {
    private Contract() {
    };

    public static final class Entry implements BaseColumns {
        public final static String TABLE_RUEN = "ruen";
        public final static String TABLE_ENRU = "enru";

        public final static String _ID = BaseColumns._ID;
        public final static String COLUMN_SLOVO = "slovo";
        public final static String COLUMN_PEREVOD = "perevod";
        public final static String COLUMN_IZBRANNOE = "izbrannoe";
    }
}

数据库助手类:

public class DBHeler extends SQLiteOpenHelper {
    //Пусть к БД
    private static String DB_PATH = "/data/data/tests.mytest/databases/";
    //Имя файла базы данных
    private static final String DATABASE_NAME = "dbase.db";
    //Версия базы данных. При изменении схемы увеличить на единицу
    private static final int DATABASE_VERSION = 1;
    //Объектная переменная типа SQLiteDatabase
    public SQLiteDatabase database;
    private Context myContext;

    final String ruQuery = "SELECT * " + " FROM " + Contract.Entry.TABLE_RUEN;
    //запрос, позволяет вывести все слова из колонки word
    final String enQuery = "SELECT * " + " FROM " + Contract.Entry.TABLE_ENRU;

    //Конструктор
    //Третий параметр null в суперклассе используется для работы с курсорами. Сейчас их не используем, поэтому оставим в покое.
    public DBHeler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.myContext = context;
    }

    public Cursor getRuWords() {
        return database.rawQuery(ruQuery, null); //в курсор выбираем все слова из запроса
    }

    public Cursor getEnWords() {
        return database.rawQuery(enQuery, null); //в курсор выбираем все слова из запроса
    }

    public void createDataBase() throws IOException {
        boolean dbExist = checkDataBase();

        if(dbExist){
            //ничего не делать - база уже есть
        }else{
            //вызывая этот метод создаем пустую базу, позже она будет перезаписана
            this.getReadableDatabase();

            try {
                copyDataBase();
            } catch (IOException e) {
                throw new Error("Error copying database");
            }
        }
    }

    private boolean checkDataBase(){
        SQLiteDatabase checkDB = null;
        try {
            String myPath = DB_PATH + DATABASE_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
        } catch(SQLiteException e){
            //база еще не существует
        }
        if(checkDB != null){
            checkDB.close();
        }
        return checkDB != null ? true : false;
    }

    private void copyDataBase() throws IOException{
        //Открываем локальную БД как входящий поток
        InputStream myInput = myContext.getAssets().open(DATABASE_NAME);

        //Путь ко вновь созданной БД
        String outFileName = DB_PATH + DATABASE_NAME;

        //Открываем пустую базу данных как исходящий поток
        OutputStream myOutput = new FileOutputStream(outFileName);

        //перемещаем байты из входящего файла в исходящий
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer))>0){
            myOutput.write(buffer, 0, length);
        }

        //закрываем потоки
        myOutput.flush();
        myOutput.close();
        myInput.close();
    }

    public void openDataBase() throws SQLException {
        //открываем БД
        String myPath = DB_PATH + DATABASE_NAME;
        //database = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
        database = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
    }

    @Override
    public synchronized void close() {
        if(database != null)
            database.close();
        super.close();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

问题:

使用btnIzbrannoe.setOnClickListener(new View.OnClickListener()添加到收藏夹的方法,它起作用了,但是当我第二次点击btnIzbrannoe从收藏夹中移除时,它不起作用。那些。不会从收藏夹中删除。按钮的图标发生变化,实际上并没有从收藏夹中删除。

java
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Iman
    2020-01-07T20:52:21Z2020-01-07T20:52:21Z

    您在 MainActivity 中更改它

    from = new String[] {Contract.Entry._ID, Contract.Entry.COLUMN_SLOVO, Contract.Entry.COLUMN_SLOVO, Contract.Entry.COLUMN_IZBRANNOE};
    

    同样在适配器周围的 bindView 的开始处

    String bukva = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_SLOVO)).substring(0, 1).toUpperCase();
        final String slovo = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_SLOVO));
        final String izbrannoe = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_IZBRANNOE));
    

    添加

    int _ID = cursor.getInt(cursor.getColumnIndex(Contract.Entry._ID));
    

    然后在初始化后btnIzbrannoe添加:

    btnIzbrannoe.setTag(_ID);
    

    和听众:

    btnIzbrannoe.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String id = String.valueOf(view.getTag());
                    Cursor getFav = db.rawQuery("SELECT * FROM " + Contract.Entry.TABLE_RUEN + " WHERE " + Contract.Entry._ID + " = " + id, null);
                    if(getFav != null && getFav.moveToFirst()){
                        String izbrannoe = getFav.getString(getFav.getColumnIndex(Contract.Entry.COLUMN_IZBRANNOE));
                        if (izbrannoe.equals("1")) {
                            ContentValues values = new ContentValues();
                            values.put(Contract.Entry.COLUMN_IZBRANNOE, "0");
                            long newRowId = db.database.update(Contract.Entry.TABLE_RUEN, values, Contract.Entry.COLUMN_SLOVO + "= ?", new String[]{slovo});
                            if (newRowId == -1) {
                                Toast.makeText(ctx, "Ошибка", Toast.LENGTH_SHORT).show();
                            } else {
                                Toast.makeText(ctx, "Удалено из избранное", Toast.LENGTH_SHORT).show();
                                btnIzbrannoe.setImageResource(R.drawable.icon_star_outline_black);
                            }
                        } else if (izbrannoe.equals("0")) {
                            ContentValues values = new ContentValues();
                            values.put(Contract.Entry.COLUMN_IZBRANNOE, "1");
                            long newRowId = db.database.update(Contract.Entry.TABLE_ENRU, values, Contract.Entry.COLUMN_SLOVO + "= ?", new String[]{slovo});
                            if (newRowId == -1) {
                                Toast.makeText(ctx, "Ошибка", Toast.LENGTH_SHORT).show();
                            } else {
                                Toast.makeText(ctx, "Добавлено в избранное", Toast.LENGTH_SHORT).show();
                                btnIzbrannoe.setImageResource(R.drawable.icon_star_yellow);
                            }
                        }
                        if(!getFav.isClosed()){
                            getFav.close();
                        }
                    }
                }
            });
    
    • 0
  2. Best Answer
    pavlofff
    2020-01-07T22:37:18Z2020-01-07T22:37:18Z

    该问题与您对数据库进行更改有关,并且您在处理单击时导航的光标值仍保留在旧数据中。作为解决方案,您可以使用数组 - 一个局部变量,用于存储当前会话中收藏夹的当前状态:

    public class MyCursorAdapter extends SimpleCursorAdapter {
        private int layout;
        DBHeler db;
        Context ctx;
        boolean[] favorite;
    
        MyCursorAdapter(Context ctx, int layout, Cursor cursor, String[] from, int[] to, DBHeler db) {
            super(ctx, layout, cursor, from, to);
            this.layout = layout;
            this.db = db;
            this.ctx = ctx;
            favorite = new boolean[cursor.getCount()];
            // заполняем первоначальные состояния избранного из БД
            int i = 0;
            while (cursor.moveToNext() ) {
              String fav = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_IZBRANNOE));
              favorite[i] = (fav.equals("1")) ? true: false;
              i = i++;
            }
         // восстанавливаем позицию курсора после итерации
         cursor.moveToPosition(-1); 
        }
    
        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
            View view = inflater.inflate(layout, parent, false);
            return view;
        }
    
        @Override
        public void bindView(View view, Context context, Cursor cursor) {
    
            String bukva = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_SLOVO)).substring(0, 1).toUpperCase();
            final String slovo = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_SLOVO));
            // текущая позиция в курсоре
            final int pos = cursor.getPosition();
    
            TextView txtBukva = (TextView) view.findViewById(R.id.txtBukva);
            TextView txtSlovo = (TextView) view.findViewById(R.id.txtSlovo);
            final ImageButton btnIzbrannoe = (ImageButton) view.findViewById(R.id.btnIzbrannoe);
    
            txtBukva.setText(bukva);
            txtSlovo.setText(slovo);
            btnIzbrannoe.setFocusable(false);
    
            if (favorite[pos]) {
                btnIzbrannoe.setImageResource(R.drawable.icon_star_yellow);
            } else  {
                btnIzbrannoe.setImageResource(R.drawable.icon_star_outline_black);
            }
    
            btnIzbrannoe.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (favorite[pos]) {
                        ContentValues values = new ContentValues();
                        values.put(Contract.Entry.COLUMN_IZBRANNOE, "0");
                        long newRowId = db.database.update(Contract.Entry.TABLE_RUEN, values, Contract.Entry.COLUMN_SLOVO + "= ?", new String[]{slovo});
                        if (newRowId == -1) {
                            Toast.makeText(ctx, "Ошибка", Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(ctx, "Удалено из избранное", Toast.LENGTH_SHORT).show();
                            btnIzbrannoe.setImageResource(R.drawable.icon_star_outline_black);
    
                        }
                    } else {
                        ContentValues values = new ContentValues();
                        values.put(Contract.Entry.COLUMN_IZBRANNOE, "1");
                        long newRowId = db.database.update(Contract.Entry.TABLE_RUEN, values, Contract.Entry.COLUMN_SLOVO + "= ?", new String[]{slovo});
                        if (newRowId == -1) {
                            Toast.makeText(ctx, "Ошибка", Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(ctx, "Добавлено в избранное", Toast.LENGTH_SHORT).show();
                            btnIzbrannoe.setImageResource(R.drawable.icon_star_yellow);
                        }
                    }
                    // инвертируем значение в вспомогательном массиве
                    favorite[pos] = !favorite[pos];
                }
            });
        }
    }
    

    我写了“在我的膝盖上”,可能存在小缺陷,但我认为一般算法是可以理解的

    НО! я бы сделал все совершенно иначе, но это большой объем работы. Во первых использовал класс CursorLoader для подгрузки данных из БД в список, он решает несколько серьезных проблем, как актуальность курсора, своевременное закрытие и сохранение при изменении состояния, асинхронная работа не тормозящая UI. Всю логику управления избранным вынес из адаптера в активити (обработку клика по кнопке избранного), это позволит отвязаться от фиксированного курсора.

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5