Урок 136. CursorLoader

Обсуждение уроков
Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 136. CursorLoader

Сообщение Foenix » 29 янв 2015, 13:32

конечно нет
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: Урок 136. CursorLoader

Сообщение doter.ua » 29 янв 2015, 13:37

Гугл "тразакция" (все или ничего )
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

Аватара пользователя
Fry
Сообщения: 183
Зарегистрирован: 07 дек 2013, 22:07

Re: Урок 136. CursorLoader

Сообщение Fry » 30 янв 2015, 10:40

Нашел. Оказывается, транзакции были в уроке 38
http://startandroid.ru/ru/uroki/vse-uro ... qlite.html

Подтверждаю, работает гораздо быстрее на больших операциях с БД. Еще раз спасибо Foenix за наводку.

Я так понимаю, транзакции можно (и нужно) оборачивать в те же конструкции, что и прямые операции с БД (insert, update, delete). Например в AsyncQueryHandler.

Все так?
Arbeit macht Fry

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 136. CursorLoader

Сообщение Foenix » 30 янв 2015, 12:05

да, но чаще в транзакции оборачивают Batch команды, тебе их применять надо при множественном insert-е.
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

LLIPAM
Сообщения: 24
Зарегистрирован: 11 фев 2015, 06:55

Re: Урок 136. CursorLoader

Сообщение LLIPAM » 11 фев 2015, 07:05

Работая над данным урок решил видоизменять его, но столкнулся с ошибкой, с которой сам не могу разобраться.
Собственно код:
DB.java

Код: Выделить всё


import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DB {
    String city[]={"Абакан", "Черногорск", "Минусинск", "Красноярск","Москва","Санкт-Питербург","Новосибирск",
            "Новокузнецк","Екатеренбург","Нижний Новгород","Казань","Самара","Челябинск","Омск",
            "Ростов-на-Дону","Уфа","Пермь","Волгоград","Воронеж"};
    private static final String DB_NAME = "AutoLab";
    private static final int DB_VERSION = 1;
    private static final String DB_TABLE = "city";
    public static final String COLUMN_ID = "_id";
    public static final String COLUMN_TXT = "city";
    private static final String DB_CREATE =
            "create table " + DB_TABLE + "(" +
                    COLUMN_ID + " integer primary key autoincrement, " +
                    COLUMN_TXT + " text" +
                    ");";
    private final Context mCtx;
    private DBHelper mDBHelper;
    private SQLiteDatabase mDB;
    public DB(Context ctx) {
        mCtx = ctx;
    }
    // открыть подключение
    public void open() {
        mDBHelper = new DBHelper(mCtx, DB_NAME, null, DB_VERSION);
        mDB = mDBHelper.getWritableDatabase();
    }
    // закрыть подключение
    public void close() {
        if (mDBHelper!=null) mDBHelper.close();
    }
    // получить все данные из таблицы DB_TABLE
    public Cursor getAllData() {
        return mDB.query(DB_TABLE, null, null, null, null, null, null);
    }
    // добавить запись в DB_TABLE
    public void addRec(String txt) {
        ContentValues cv = new ContentValues();
        cv.put(COLUMN_TXT, txt);
        mDB.insert(DB_TABLE, null, cv);
    }
    // удалить запись из DB_TABLE
    public void delRec(long id) {
        mDB.delete(DB_TABLE, COLUMN_ID + " = " + id, null);
    }
    // класс по созданию и управлению БД
    private class DBHelper extends SQLiteOpenHelper {
        public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,
                        int version) {
            super(context, name, factory, version);
        }
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(DB_CREATE);
                 ContentValues cv = new ContentValues();
                // заполним таблицу
                for (int i = 0; i < 20; i++) {
                    cv.put(COLUMN_TXT, city[i]);
                    db.insert(DB_TABLE, null, cv);
                }

        }

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

            }
        }
    }
MainActivity.java:

Код: Выделить всё

import java.util.concurrent.TimeUnit;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.widget.ListView;

public class MainActivity extends FragmentActivity implements LoaderCallbacks<Cursor> {
    private static final int CM_DELETE_ID = 1;
    ListView lvData;
    DB db;
    SimpleCursorAdapter scAdapter;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // открываем подключение к БД
        db = new DB(this);
        db.open();
        // формируем столбцы сопоставления
        String[] from = new String[] {DB.COLUMN_TXT };
        int[] to = new int[] { R.id.tvText };

        // создааем адаптер и настраиваем список
        scAdapter = new SimpleCursorAdapter(this, R.layout.city, null, from, to, 0);
        lvData = (ListView) findViewById(R.id.lvData);
        lvData.setAdapter(scAdapter);

        // добавляем контекстное меню к списку
        registerForContextMenu(lvData);

        // создаем лоадер для чтения данных
        getSupportLoaderManager().initLoader(0, null, this);

    }
    protected void onDestroy() {
        super.onDestroy();
        // закрываем подключение при выходе
        db.close();
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle bndl) {
        return new MyCursorLoader(this, db);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        scAdapter.swapCursor(cursor);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
    }

    static class MyCursorLoader extends CursorLoader {

        DB db;

        public MyCursorLoader(Context context, DB db) {
            super(context);
            this.db = db;
        }

        @Override
        public Cursor loadInBackground() {
            Cursor cursor = db.getAllData();
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return cursor;
        }

    }
}
Где я ошибся? куда мне копать?

Ошибка: java.lang.RuntimeException: Unable to start activity ComponentInfo{ru.android.llipam.lli_autolab/ru.android.llipam.lli_autolab.MainActivity}: java.lang.ArrayIndexOutOfBoundsException: length=19; index=19

LLIPAM
Сообщения: 24
Зарегистрирован: 11 фев 2015, 06:55

Re: Урок 136. CursorLoader

Сообщение LLIPAM » 11 фев 2015, 07:18

Вот что интересно изменил цикл в DB.java:

Код: Выделить всё

// заполним таблицу
                for (int i = 0; i < 19; i++) {
                    cv.put(COLUMN_TXT, city[i]);
                    db.insert(DB_TABLE, null, cv);
                }
Список отображается как я и хотел, но ошибку при этом выдает все ту же. От куда эта ошибка и на что она влияет?

Аватара пользователя
klblk
Сообщения: 1097
Зарегистрирован: 18 окт 2012, 11:17
Откуда: г. Красноярск

Re: Урок 136. CursorLoader

Сообщение klblk » 11 фев 2015, 07:47

0) Интересный список городов. Сам просто родом из Минусинского района и видеть Абакан, Минусинск, Черногорск наряду с другими куда более известными городами России забавно=)
1) ArrayIndexOutOfBoundsException - говорит что вы вышли за рамки массива, у вас массив имеет индексы от 0 до 18, а 19 не существует элемента, следовательно исправив цикл ошибка ушла. Если ошибка все-таки осталась, то она скорее всего в другом месте или просто другая.

LLIPAM
Сообщения: 24
Зарегистрирован: 11 фев 2015, 06:55

Re: Урок 136. CursorLoader

Сообщение LLIPAM » 11 фев 2015, 10:35

Просто я родом из Черногорска =) поэтому и список такой. Только начал осваивать программирование под андроид да и вообще джаву) так что остается много вопрос, кстати один из них как мне можно получить название города кликнув по нему? Есть метода :

Код: Выделить всё

lvData.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
                Log.d(LOG_TAG, "itemClick: city = " + position + ", id = "
                        + id);
            }
        });
Но он может возвратить только ид и позицию, но мне нужно получить строковую константу, то есть название города. Подскажите куда копать? какие методы посмотреть? или можно как то внутри этого метода получить название города? =)

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 136. CursorLoader

Сообщение Foenix » 11 фев 2015, 11:56

копать - в уроки. ТАм все это описывается.

Что же касается массива - нужно везде указывать не константы, а метод - длину массива. И всегда от нее плясать.
Ну и по ссылкам в подписи.
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

LLIPAM
Сообщения: 24
Зарегистрирован: 11 фев 2015, 06:55

Re: Урок 136. CursorLoader

Сообщение LLIPAM » 12 фев 2015, 06:21

В интернете нашел метод getItemAtPosition(position).

Применяю его в своем коде:

Код: Выделить всё

Toast.makeText(getApplicationContext(),"Вы выбрали город = "
                        + lvData.getItemIdAtPosition(position).toString(),Toast.LENGTH_SHORT ).show();
но toString выделяется красным цветом и работать отказывается
полный код:

Код: Выделить всё

import java.util.concurrent.TimeUnit;

import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends FragmentActivity implements LoaderCallbacks<Cursor> {

    final String LOG_TAG = "myLogs";


    private static final int CM_DELETE_ID = 1;

    ListView lvData;
    DB db;

    SimpleCursorAdapter scAdapter;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // открываем подключение к БД
        db = new DB(this);
        db.open();
        // формируем столбцы сопоставления
        String[] from = new String[] {DB.COLUMN_TXT };
        int[] to = new int[] { R.id.tvText };

        // создааем адаптер и настраиваем список
        scAdapter = new SimpleCursorAdapter(this, R.layout.city, null, from, to, 0);
        lvData = (ListView) findViewById(R.id.lvData);
        lvData.setAdapter(scAdapter);

        lvData.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
               // Log.d(LOG_TAG, "itemClick: city = " + position + ", id = "
                   //     + id);
                Toast.makeText(getApplicationContext(),"Вы выбрали город = "
                        + lvData.getItemIdAtPosition(position).toString(),Toast.LENGTH_SHORT ).show();
            }
        });

        // добавляем контекстное меню к списку
        registerForContextMenu(lvData);

        // создаем лоадер для чтения данных
        getSupportLoaderManager().initLoader(0, null, this);
    }
    protected void onDestroy() {
        super.onDestroy();
        // закрываем подключение при выходе
        db.close();
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle bndl) {
        return new MyCursorLoader(this, db);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        scAdapter.swapCursor(cursor);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
    }

    static class MyCursorLoader extends CursorLoader {

        DB db;

        public MyCursorLoader(Context context, DB db) {
            super(context);
            this.db = db;
        }

        @Override
        public Cursor loadInBackground() {
            Cursor cursor = db.getAllData();
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return cursor;
        }
    }
}
Подскажите что делаю не так?

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: Урок 136. CursorLoader

Сообщение doter.ua » 12 фев 2015, 10:22

Итем итак сринга.
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

LLIPAM
Сообщения: 24
Зарегистрирован: 11 фев 2015, 06:55

Re: Урок 136. CursorLoader

Сообщение LLIPAM » 12 фев 2015, 10:36

Вот к чему я пришел, изменил немного код:

Код: Выделить всё

 lvData.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
                String selectedItem=lvData.getItemAtPosition(position).toString();
               Log.d(LOG_TAG, "itemClick: city = " + selectedItem + ", id = "
                       + id);  
Теперь в логе у меня выводится:
itemClick: city = android.database.sqlite.SQLiteCursor@b3db5a98, id = 1

Как вместо вот этого android.database.sqlite.SQLiteCursor@b3db5a98 получить нормальную строку?

LLIPAM
Сообщения: 24
Зарегистрирован: 11 фев 2015, 06:55

Re: Урок 136. CursorLoader

Сообщение LLIPAM » 13 фев 2015, 04:08

Похоже мне никто не поможет =(

Cliffman
Сообщения: 8
Зарегистрирован: 05 мар 2015, 16:12

Re: Урок 136. CursorLoader

Сообщение Cliffman » 05 мар 2015, 17:04

ошибка The method initLoader(int, Bundle, LoaderManager.LoaderCallbacks<D>) in the type LoaderManager is not applicable for the arguments (int, null, ListActivity)

в строке getSupportLoaderManager().initLoader(0, null, this);


мой импорт

Код: Выделить всё

import java.util.concurrent.TimeUnit;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
import android.widget.TextView;
extends FragmentActivity есть
мин minSdkVersion="12" (в инете нашел, что ниже 11 сдк может давать такую ошибку)

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: Урок 136. CursorLoader

Сообщение doter.ua » 05 мар 2015, 17:16

Cliffman писал(а):ошибка The method initLoader(int, Bundle, LoaderManager.LoaderCallbacks<D>) in the type LoaderManager is not applicable for the arguments (int, null, ListActivity)

в строке getSupportLoaderManager().initLoader(0, null, this);


мой импорт

Код: Выделить всё

import java.util.concurrent.TimeUnit;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
import android.widget.TextView;
extends FragmentActivity есть
мин minSdkVersion="12" (в инете нашел, что ниже 11 сдк может давать такую ошибку)
Ругается на передаваемые аргументы, что-то не то передаешь.
initLoader (int id, Bundle args, LoaderCallbacks<D> callback)
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

Cliffman
Сообщения: 8
Зарегистрирован: 05 мар 2015, 16:12

Re: Урок 136. CursorLoader

Сообщение Cliffman » 05 мар 2015, 18:14

передаю все тоже что и в уроке,

до єтого ругалось на

getSupportLoaderManager().initLoader(0, null, this);

но

public class MainActivity extends FragmentActivity

помог

LLIPAM
Сообщения: 24
Зарегистрирован: 11 фев 2015, 06:55

Re: Урок 136. CursorLoader

Сообщение LLIPAM » 06 мар 2015, 07:34

Собственно Файл DB.java:

Код: Выделить всё


import android.content.ContentValues;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

public class DB {
    String city[]={"test","test","test","test","test","test","test","test","test","test","test","test","test","test","test",
            "test","test","test","test","test","test","test","test","test","test","test","test","test","test","test",
            "test","test","test","test","test","test","test","test","test","test","test","test","test"
    };

    String cto[]={"test123","test123","test123","test123","test123","test123","test123","test123","test123","test123",
            "test123","test123","test123","test123","test123","test123","test123","test123","test123","test123","test123",
            "test123","test123","test123","test123","test123","test123","test123","test123","test123","test123","test123",
            "test123","test123","test123","test123","test123","test123","test123","test123","test123","test123","test123"};

    private static final String DB_NAME = "AutoLab";
    private static final int DB_VERSION = 1;

    private static final String DB_TABLE = "city";
    public static final String COLUMN_ID = "_id";
    public static final String COLUMN_TXT = "city";

    private static final String DB_CTO = "cto";
    public static final String CTO_ID = "_id";
    public static final String CTO_TXT = "cto";

    private static final String DB_CREATE =
            "create table " +
                    DB_TABLE + "(" +
                    COLUMN_ID + " integer primary key autoincrement, " +
                    COLUMN_TXT + " text" +
                    ");";

    private static final String CTO_CREATE =
            "create table " +
                    DB_CTO + "(" +
                    CTO_ID + " integer primary key autoincrement, " +
                    CTO_TXT + " text" +
                    ");";

    private final Context mCtx;
    private DBHelper mDBHelper;
    private SQLiteDatabase mDB;
    public DB(Context ctx) {
        mCtx = ctx;
    }
    // открыть подключение
    public void open() {
        mDBHelper = new DBHelper(mCtx, DB_NAME, null, DB_VERSION);
        mDB = mDBHelper.getWritableDatabase();
    }
    // закрыть подключение
    public void close() {
        if (mDBHelper!=null) mDBHelper.close();
    }
    // получить все данные из таблицы DB_TABLE
    public Cursor getAllData() {
        return mDB.query(DB_TABLE, null, null, null, null, null, null);
    }

     // класс по созданию и управлению БД
    private class DBHelper extends SQLiteOpenHelper {
        public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,
                       int version) {
            super(context, name, factory, version);
        }
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(DB_CREATE);
            ContentValues cv = new ContentValues();
            // заполним таблицу
            for (int i = 0; i < city.length; i++) {
                cv.put(COLUMN_TXT, city[i]);
                db.insert(DB_TABLE, null, cv);
            }
            db.execSQL(CTO_CREATE);
            for (int i = 0; i < cto.length; i++) {
                cv.put(CTO_TXT, cto[i]);
                db.insert(DB_CTO, null, cv);
            }
        }
        @Override
        public void onUpgrade (SQLiteDatabase db,int oldVersion, int newVersion){

        }

    }
}
Таблица city создается и заполняется, но таблица cto создается но не заполняется. Что я делаю не так?

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 136. CursorLoader

Сообщение Foenix » 06 мар 2015, 08:16

не знаю почему не заполняется
сделай cv.clear() или как-то так перед заполнением второй таблицы
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

LLIPAM
Сообщения: 24
Зарегистрирован: 11 фев 2015, 06:55

Re: Урок 136. CursorLoader

Сообщение LLIPAM » 06 мар 2015, 08:46

Помогло спс =)

LLIPAM
Сообщения: 24
Зарегистрирован: 11 фев 2015, 06:55

Re: Урок 136. CursorLoader

Сообщение LLIPAM » 06 мар 2015, 14:31

У меня еще есть один вопрос.
В файле DB.java я сделал выборку данных:

Код: Выделить всё

public Cursor getCity_CTO() {

        String sqlQuery = "select ct._id, ct.cto, ci.city as city "
                + "From cto as ct "
                + "INNER JOIN city ci "
                + "on ct.city_id = ci._id "
                + "where city = ?";
    return mDB.rawQuery(sqlQuery, new String[] {"Test"});

    }
Все работает, но вместо {"Test"} мне нужно переда переменную Например Ci_test.
Эта переменная должна зависеть от того от введенных данных в MainActivity. Или браться из преференса.
Передать эту переменную через Intent не получается. И так же вытащить из преференса не могу, так как DB.java не является Activity. Как можно получить эту переменную?

Ответить