Android. Lection 4
ListView and SQLite
Expected result




Navigating through activities

Top level activities
These are the activities your user will encounter first, so they go at the top.
Category activities
Your users will navigate from the top-level activity to the category activities. In complex apps, you might have several layers of categories and subcategories.
Details/Edit activities
These form the bottom layer of the activity hierarchy. Users will navigate to these from the category activities.
Structure

Steps
- Add the Drink class and image resources
- Create MainActivity and it's layout
- Create DrinkCategoryActivity
- Create DrinkActivity and it's layout

public class Drink {
private String name;
private String description;
private int imageResId;
public Drink(String name, String description, int imageResId) {
this.name = name;
this.description = description;
this.imageResId = imageResId;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public int getImageResId() {
return imageResId;
}
@Override
public String toString() {
return name;
}
}
Drink
Structure

Resources


<resources>
<string name="app_name">Recipes</string>
<string-array name="main_activity_menu">
<item>Drinks</item>
<item>Food</item>
<item>Stores</item>
</string-array>
</resources>
<resources>
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="title_size">100dp</dimen>
<dimen name="image_size_default">150dp</dimen>
</resources>
dimens.xml
strings.xml
MainActivity layout
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.cadacademy.sutula.lection4.MainActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="@dimen/title_size"
android:id="@+id/imageView"
android:src="@drawable/title_logo"
android:longClickable="false" />
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/listView"
android:entries="@array/main_activity_menu"/>
</LinearLayout>

ListView




OnItemClickListener
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent,
View view,
int position,
long id) {
switch (position) {
case 0:
Intent intent
= new Intent(MainActivity.this, DrinkCategoryActivity.class);
startActivity(intent);
break;
default:
break;
}
}
});
Butter Knife
class ExampleActivity extends Activity {
@Bind(R.id.title) TextView title;
@Bind(R.id.subtitle) TextView subtitle;
@Bind(R.id.footer) TextView footer;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.bind(this);
// TODO Use fields...
}
}public void bind(ExampleActivity activity) {
activity.subtitle = (android.widget.TextView) activity.findViewById(2130968578);
activity.footer = (android.widget.TextView) activity.findViewById(2130968579);
activity.title = (android.widget.TextView) activity.findViewById(2130968577);
}dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.jakewharton:butterknife:7.0.1'
}How to install

MainActivity.java
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import butterknife.Bind;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity {
@Bind(R.id.listView) ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent,
View view,
int position,
long id) {
switch (position) {
case 0:
Intent intent
= new Intent(MainActivity.this, DrinkCategoryActivity.class);
startActivity(intent);
break;
default:
break;
}
}
});
}
}
ListActivity
A list activity is type of activity that specializes in working with a list. It’s automatically bound to a list view, so you don’t need to create one yourself. Here’s what one looks like:

For nonstatic data, use an adapter
If you need to display data in a list view that comes from a nonstatic source such as a Java array or database, you need to use an adapter. An adapter acts as a bridge between the data source and the list view:

How to use
Drink[] drinks = {
new Drink("Bloody Mary", "Bloody Mary desc", R.drawable.blood_marry),
new Drink("Sazerac", "Sazerac drink", R.drawable.sazarac),
new Drink("B52", "B52 drink", R.drawable.b52),
new Drink("Cider", "Cider drink", R.drawable.sydr)
};
ArrayAdapter<Drink> listAdapter = new ArrayAdapter<Drink>(this,
android.R.layout.simple_expandable_list_item_1,
drinks);
ListView listView = getListView();
listView.setAdapter(listAdapter);
What happens
OnListItemClick
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(this, DrinkActivity.class);
intent.putExtra(DrinkActivity.DRINK_NO, (int) id);
startActivity(intent);
}DrinkCategoryActivity
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class DrinkCategoryActivity extends ListActivity {
public final static Drink[] drinks = {
new Drink("Bloody Mary", "Bloody Mary desc", R.drawable.blood_marry),
new Drink("Sazerac", "Sazerac drink", R.drawable.sazarac),
new Drink("B52", "B52 drink", R.drawable.b52),
new Drink("Cider", "Cider drink", R.drawable.sydr)
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayAdapter<Drink> listAdapter = new ArrayAdapter<Drink>(this,
android.R.layout.simple_expandable_list_item_1,
drinks);
ListView listView = getListView();
listView.setAdapter(listAdapter);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(this, DrinkActivity.class);
intent.putExtra(DrinkActivity.DRINK_NO, (int) id);
startActivity(intent);
}
}
Drink layout
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.cadacademy.sutula.lection4.DrinkActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/tvTitle"
android:layout_gravity="center_horizontal" />
<ImageView
android:layout_width="@dimen/image_size_default"
android:layout_height="@dimen/image_size_default"
android:id="@+id/photo"
android:layout_gravity="center_horizontal" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="@+id/tvDescription"
android:layout_gravity="center_horizontal" />
</LinearLayout>
DrinkActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.Bind;
import butterknife.ButterKnife;
public class DrinkActivity extends AppCompatActivity {
public final static String DRINK_NO = "DRINK_NO";
@Bind(R.id.tvTitle) TextView tvTitle;
@Bind(R.id.photo) ImageView ivPhoto;
@Bind(R.id.tvDescription) TextView tvDesc;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drink);
ButterKnife.bind(this);
int drinkNo = getIntent().getIntExtra(DRINK_NO, -1);
if (drinkNo != -1) {
Drink drink = DrinkCategoryActivity.drinks[drinkNo];
tvTitle.setText(drink.getName());
ivPhoto.setImageResource(drink.getImageResId());
tvDesc.setText(drink.getDescription());
}
}
}
Database
SQLite

Where database stored



Create SQLite Helper

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class RecipeDatabaseHelper extends SQLiteOpenHelper{
private static final String DB_NAME = "recipe";
private static final int DB_VERSION = 1;
public RecipeDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
Inside Database

Datatypes

Create Table

Insert data using insert() method
ContentValues drinkValues = new ContentValues();
drinkValues.put("NAME", "Sazerac");
drinkValues.put("DESCRIPTION", "Sazerac descr drink");
drinkValues.put("IMAGE_RESOURCE_ID", R.drawable.sazarac);
db.insert("DRINK", null, drinkValues);| _id | NAME | DESCRIPTION | IMAGE_RESOURCE_ID |
|---|---|---|---|
| 1 | Sazerac | Sazerac descr drink | 54545453 |
Update()
public int update (String table, ContentValues values,
String whereClause, String[] whereArgs)ContentValues testValue = new ContentValues();
testValue.put("DESCRIPTION", "Very tasty");
db.update("DRINK", testValue, "_id = ?", new String[]{"1"});| _id | NAME | DESCRIPTION | IMAGE_RESOURCES_ID |
|---|---|---|---|
| 1 | Sazerac |
Very tasty |
54545453 |
Full code of Helper
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class RecipeDatabaseHelper extends SQLiteOpenHelper{
private static final String DB_NAME = "recipe";
private static final int DB_VERSION = 1;
public RecipeDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE DRINK ("
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "NAME TEXT, "
+ "DESCRIPTION TEXT, "
+ "IMAGE_RESOURCE_ID INTEGER);");
insertDrink(db, "Bloody Mary", "Bloody Mary desc", R.drawable.blood_marry);
insertDrink(db, "Sazerac", "Sazerac drink", R.drawable.sazarac);
insertDrink(db,"B52", "B52 drink", R.drawable.b52);
insertDrink(db,"Cider", "Cider drink", R.drawable.sydr);
}
private void insertDrink(SQLiteDatabase db, String name, String description, int imageResId) {
ContentValues drinkValues = new ContentValues();
drinkValues.put("NAME", name);
drinkValues.put("DESCRIPTION", description);
drinkValues.put("IMAGE_RESOURCE_ID", imageResId);
db.insert("DRINK", null, drinkValues);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
Query()
A database query gives you a way of saying exactly which records you want access to from the database. As an example, you can say you want to access all the data from the DRINK table, or just those drinks whose name begins with “L”. The more you can restrict the data you return, the more efficient your query will be.

Example
Cursor cursor = db.query("DRINK", new String[] {"NAME", "DESCRIPTION"},
null, null, null, null, null);The simplest type of database query you can create is to return all the records for particular columns without specifying criteria.
| NAME | DESCRIPTION |
|---|---|
| Bloody Mary | Bloody Mary desc |
| Sazerac | Sazerac drink |
| B52 | B52 drink |
| Cider | Cider drink |
Example
Cursor cursor = db.query("Drink",
new String[] {"_id", "NAME", "DESCRIPTION"},
"_id = ?",
new String[] {Integer.toString(1)},
null, null, null);| _id | NAME | DESCRIPTION |
|---|---|---|
| 1 | Bloody Mary | Bloody Mary desc |
getReadableDatabase() versus getWritableDatabase()



How to get info from Cursor
//Move to the first record in the Cursor
if (cursor.moveToFirst()) {
//Get the drink details from the cursor
String nameText = cursor.getString(0);
String descriptionText = cursor.getString(1);
int photoId = cursor.getInt(2);
// process data
}
cursor.close();
db.close();Cursor Adapter



Closing Cursor and Database
@Override
public void onDestroy(){
super.onDestroy();
cursor.close();
db.close();
}Final structure

Copy of Android
By Sania Sutula
Copy of Android
- 381