Урок 136. CursorLoader

Обсуждение уроков
Ярослав
Сообщения: 4
Зарегистрирован: 15 июл 2014, 15:07

Re: Урок 136. CursorLoader

Сообщение Ярослав » 15 июл 2014, 15:50

KamiSempai, спасибо!

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Урок 136. CursorLoader

Сообщение altwin » 15 июл 2014, 15:54

KamiSempai писал(а):
altwin писал(а):существует такое понятие, как pagination, подразумевающее ограничение выдачи с последующей возможностью пролистывания( помоему для определения -это коряво звучит :) ) и применимо оно к любой коллекции. Вам нужно идти в сторону custom listview.
Это, что, тролинг???

Ярослав, нужно делать кастомный адаптер и сжимать изображения перед отображением в списке.
Это должно помочь: viewtopic.php?f=3&t=2961&p=32859#p32596
Неа, это фундаментальная основа pull to refresh патерна. Просто я не вижу более наглядного способа объяснить принцип загрузки в память только видимой части контента, чем постраничный вывод. Ну и как бы в абстрактном восприятии видимой части listview с ее содержимым, в качестве страницы -ничего плохого я не вижу. А отличия в том, чтобы грузить следующую страницу( группу элементов ) или один элемент формирующий listview - не существенны в данном случае... хотя на последнюю инстанцию я не претендую и рад буду если меня кто - то чему -то новому научит ;)
Изображение

Аватара пользователя
KamiSempai
Сообщения: 1339
Зарегистрирован: 17 фев 2012, 21:23
Откуда: Мордор

Re: Урок 136. CursorLoader

Сообщение KamiSempai » 15 июл 2014, 16:07

altwin писал(а):
KamiSempai писал(а):
altwin писал(а):существует такое понятие, как pagination, подразумевающее ограничение выдачи с последующей возможностью пролистывания( помоему для определения -это коряво звучит :) ) и применимо оно к любой коллекции. Вам нужно идти в сторону custom listview.
Это, что, тролинг???
Неа, это фундаментальная основа pull to refresh патерна. Просто я не вижу более наглядного способа объяснить принцип загрузки в память только видимой части контента, чем постраничный вывод. Ну и как бы в абстрактном восприятии видимой части listview с ее содержимым, в качестве страницы -ничего плохого я не вижу. А отличия в том, чтобы грузить следующую страницу( группу элементов ) или один элемент формирующий listview - не существенны в данном случае... хотя на последнюю инстанцию я не претендую и рад буду если меня кто - то чему -то новому научит ;)
Тут не в этом проблема. Я более чем уверен, что он загружает только видимую часть контента. Просто, если, даже в маленький ImageView загрузить фотографию в HD качестве - это будет потреблять большое количество ресурсов и постраничная прокрутка тут не поможет.
Перед выводом картинки в список ее обязательно нужно ужимать до необходимых размеров. Многие это не знают. В итоге получаем тормознутые приложения даже в топах Google Play. Я такие видел. Видимо, создатель поленился сделать миниатюры для изображений.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

Ярослав
Сообщения: 4
Зарегистрирован: 15 июл 2014, 15:07

Re: Урок 136. CursorLoader

Сообщение Ярослав » 15 июл 2014, 16:10

KamiSempai, расскажите про создание миниатюр для изображений.

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Урок 136. CursorLoader

Сообщение altwin » 15 июл 2014, 16:20

Ярослав писал(а):KamiSempai, расскажите про создание миниатюр для изображений.
Посмотрите лучше на работаюие примеры: функция createScaledBitmap делает то, что вам нужно. Либо вот популярная библиотека позволяющая грузить image из url и выводить в том чисте в listView, там вы найдете много интересного внутри даже с кешированием картинок https://github.com/nostra13/Android-Uni ... Utils.java
Изображение

voffka
Сообщения: 1
Зарегистрирован: 22 авг 2014, 13:07

Re: Урок 136. CursorLoader

Сообщение voffka » 22 авг 2014, 13:15

Всем добрый день ! Спасибо за инфу, узнал много нового )) Но остались и вопросы...
Я, так понял, что лоадер применяется в основном для получения информации из БД (например) и последующего ее отображения в элементах UI. А что делать с такими операциями как insert, update, delete, их можно прямо UI-потоке делать ? Так же операция чтения из БД, обработка и обновления БД, без вывода на экран ? Или их надо, например, в АсинкТаск выносить ?
И второй вопрос - как все таки правильно работать с БД из нескольких активити + из сервиса ? КонтентПровайдер или без него можно обойтись ?
Спасибо....

Mishytca
Сообщения: 1
Зарегистрирован: 10 сен 2014, 15:37

Re: Урок 136. CursorLoader

Сообщение Mishytca » 10 сен 2014, 15:46

люди добрые! помогите начинающему программисту. Я попытался изменить код урока так чтобы при нажатии на кнопку "Добавить запись" добавлялась не одна строка и картинка, а две строки и картинка. Мучаюсь второй день - не пойму что я делаю не так. Выручайте

main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/ivImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher">
</ImageView>
<TextView
android:id="@+id/tvText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:text=""
android:textSize="18sp">
</TextView>

<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" >
</TextView>

</LinearLayout>

DB.java
package ru.android.p1361_cursorloader;


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;

public class DB {

private static final String DB_NAME = "mydb";
private static final int DB_VERSION = 1;
private static final String DB_TABLE = "mytab";

public static final String COLUMN_ID = "_id";
public static final String COLUMN_IMG = "img";
public static final String COLUMN_TXT = "txt";
public static final String COLUMN_NAME = "name";

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

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, String name, int img) {
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME, name);
cv.put(COLUMN_TXT, txt);
cv.put(COLUMN_IMG, img);
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, CursorFactory factory,
int version) {
super(context, name, factory, version);
}

// создаем и заполняем БД
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DB_CREATE);

ContentValues cv = new ContentValues();

cv.put(COLUMN_NAME, "nametext ");
cv.put(COLUMN_TXT, "sometext ");
cv.put(COLUMN_IMG, R.drawable.ic_launcher);
db.insert(DB_TABLE, null, cv);

}

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

MainActivity.java

package ru.android.p1361_cursorloader;
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.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
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;

/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// открываем подключение к БД
db = new DB(this);
db.open();

// формируем столбцы сопоставления
String[] from = new String[] { DB.COLUMN_IMG, DB.COLUMN_TXT, DB.COLUMN_NAME };
int[] to = new int[] { R.id.ivImg, R.id.tvText, R.id.tvName };

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

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

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

// обработка нажатия кнопки
public void onButtonClick(View view) {
// добавляем запись
db.addRec("sometext " + (scAdapter.getCount() + 1), "name " + (scAdapter.getCount() + 1), R.drawable.ic_launcher);
// получаем новый курсор с данными
getSupportLoaderManager().getLoader(0).forceLoad();
}

public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, CM_DELETE_ID, 0, R.string.delete_record);
}

public boolean onContextItemSelected(MenuItem item) {
if (item.getItemId() == CM_DELETE_ID) {
// получаем из пункта контекстного меню данные по пункту списка
AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) item
.getMenuInfo();
// извлекаем id записи и удаляем соответствующую запись в БД
db.delRec(acmi.id);
// получаем новый курсор с данными
getSupportLoaderManager().getLoader(0).forceLoad();
return true;
}
return super.onContextItemSelected(item);
}

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(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
return cursor;
}

}
}

Аватара пользователя
Akella
Сообщения: 42
Зарегистрирован: 05 ноя 2013, 12:55
Откуда: UA
Контактная информация:

Re: Урок 136. CursorLoader

Сообщение Akella » 05 ноя 2014, 23:19

Приветствую.
Изучаю урок 136.
Использую Android Studio.
Возникла проблема на этой строке

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

scAdapter = new SimpleCursorAdapter(this, R.layout.item, null, from, to);
SimpleCursorAdapter зачеркивается и пишет, что Deprecated.

Возможно проблема в блоке import`а
вот кусок кода:

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

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;
LoaderManager, CursorLoader, Loader и SimpleCursorAdapter выделены красным шрифтом
подвожу курсор и вижу Cannot resolve sumbol 'LoaderManager'

что-то не то с версией SDK?

Что и где подсмотреть и исправить?
Спасибо.

Аватара пользователя
KamiSempai
Сообщения: 1339
Зарегистрирован: 17 фев 2012, 21:23
Откуда: Мордор

Re: Урок 136. CursorLoader

Сообщение KamiSempai » 05 ноя 2014, 23:40

Deprecated только этот конструктор класса. Нужно добавить последним параметром flag, тогда зачеркивать не будет. Можно указать 0.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

Аватара пользователя
Akella
Сообщения: 42
Зарегистрирован: 05 ноя 2013, 12:55
Откуда: UA
Контактная информация:

Re: Урок 136. CursorLoader

Сообщение Akella » 05 ноя 2014, 23:46

Спасибо!

Аватара пользователя
Akella
Сообщения: 42
Зарегистрирован: 05 ноя 2013, 12:55
Откуда: UA
Контактная информация:

Re: Урок 136. CursorLoader

Сообщение Akella » 06 ноя 2014, 00:14

Теперь проблема с getSupportLoaderManager
на строке
getSupportLoaderManager().initLoader(0, null, this);

тоже пишет, что cannot resolve method

Аватара пользователя
Akella
Сообщения: 42
Зарегистрирован: 05 ноя 2013, 12:55
Откуда: UA
Контактная информация:

Re: Урок 136. CursorLoader

Сообщение Akella » 06 ноя 2014, 00:21

если добавить
import android.support.v4.app.FragmentActivity;

то support выделяет красным

Аватара пользователя
Akella
Сообщения: 42
Зарегистрирован: 05 ноя 2013, 12:55
Откуда: UA
Контактная информация:

Re: Урок 136. CursorLoader

Сообщение Akella » 06 ноя 2014, 00:32

гугль привёл сюда
https://stackoverflow.com/questions/216 ... 8#26049978

добавил в Andriod Studio так же
http://f5.s.qip.ru/adNBVy17.png

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

Re: Урок 136. CursorLoader

Сообщение Foenix » 06 ноя 2014, 11:21

проверяй, так же, чтоб у тебя импорты не смешивались - либо саппорт либо обычная во всех классах.
R.id.team

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

Аватара пользователя
Akella
Сообщения: 42
Зарегистрирован: 05 ноя 2013, 12:55
Откуда: UA
Контактная информация:

Re: Урок 136. CursorLoader

Сообщение Akella » 06 ноя 2014, 11:53

да, это я уже понял, да и студия в таком случае даёт подсказку

Аватара пользователя
Akella
Сообщения: 42
Зарегистрирован: 05 ноя 2013, 12:55
Откуда: UA
Контактная информация:

Re: Урок 136. CursorLoader

Сообщение Akella » 06 ноя 2014, 20:43

Приветствую.

Нельзя более подробно описать этот кусок кода

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

// формируем столбцы сопоставления
    String[] from = new String[] { DB.COLUMN_IMG, DB.COLUMN_TXT };
    int[] to = new int[] { R.id.ivImg, R.id.tvText };

    // создааем адаптер и настраиваем список
    scAdapter = new SimpleCursorAdapter(this, R.layout.item, null, from, to, 0);
Список полей таблицы и список визуальных элементов должны строго совпадать и по типам и по количеству? А если полей много, типы разные? Как контролировать?

AlexKem
Сообщения: 9
Зарегистрирован: 27 авг 2014, 08:59

Re: Урок 136. CursorLoader

Сообщение AlexKem » 12 ноя 2014, 05:34

Этот урок у меня не получился. Я использую Андроид 4.2. Программа по умолчанию ставит следующие библиотеки

import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
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;

и на метод getSupportLoaderManager() выдает ошибку

предлагает поменять на getLoaderManager() или создать данный метод.

AlexKem
Сообщения: 9
Зарегистрирован: 27 авг 2014, 08:59

Re: Урок 136. CursorLoader

Сообщение AlexKem » 12 ноя 2014, 07:10

К предыдущему:
Я сделал урок, как он есть, все получилось. НО!
Разница моего предыдущего варианта лишь в том, что я создал задачу не в главном активити, а во втором. То есть, первая активити запускает второе, и вот там уже должен работать список.
Проблема та же:
на метод getSupportLoaderManager() выдает ошибку
Хотя весь текст приложения - тот же.

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

Re: Урок 136. CursorLoader

Сообщение Foenix » 12 ноя 2014, 07:57

проверь импорты - у тебя ВЕЗДЕ должна использовать саппорт-либа, во всех активити, классах и прочих.
R.id.team

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

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

Re: Урок 136. CursorLoader

Сообщение klblk » 12 ноя 2014, 09:08

вероятно наследственность плохая: попробуй вместо Activity, скажем, FragmentActivity

Ответить