ListView and SQLite
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.
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;
}
}
<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
<?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.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;
}
}
});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
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;
}
}
});
}
}
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:
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:
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);@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);
}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);
}
}
<?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>
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());
}
}
}
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) {
}
}
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 |
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 |
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) {
}
}
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.
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 |
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 |
//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();@Override
public void onDestroy(){
super.onDestroy();
cursor.close();
db.close();
}