1.ContentProvider数据共享 --- Android四大组件之一
[1]概念:数据共享本身不是数据库,它是为Sqlite关系数据库提供了共享功能。
共享数据库的优点:节约资源,可以将多个应用程序需要的数据库做成一个共享数据库。例如联系人数据库,多媒体数据库。
[2]制作共享数据库的步骤
1.定义一个类,继承ContentProvider
2.在清单文件中添加privider标签 必须填写的属性name, authorities(共享数据库地址)(命名规则:应用程序的包名+组件的类名)
3.重写ContentProvider类中的onCreate方法,创建关系数据库。给关系数据库添加共享功能。
[3]操作共享数据库
ContentResolver --- 操作共享数据库
相关方法 --- insert, update, delete, query方法。
当用户调用以上方法时,系统会自动调用ContentProvider中的insert, update, delete, query方法
[4]操作系统联系人数据库地址 ContactsContract.Contacts.CONTENT_URI
package com.farsight.contentProvider;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.net.Uri;
import android.os.Bundle;
public class Android_28_ContentProviderActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//向共享数据添加记录
ContentResolver resolver = this.getContentResolver();
// Uri 网址"http://www.baidu.com"
// Uri 共享数据库地址"content://"
//共享数据库地址
Uri url = Uri.parse("content://com.farsight.contentProiver.MyProvider");
ContentValues values = new ContentValues();
values.put(MyProvider.NAME, "ivy");
values.put(MyProvider.SCORE, 100);
//系统自动调用Myprovider中的insert方法
resolver.insert(url, values);
}
}
package com.farsight.contentProvider;
import android.content.ContentProvider;
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.net.Uri;
import android.util.Log;
//共享数据库对象在安装应用程序时创建
//系统自动调用onCreate方法
public class MyProvider extends ContentProvider {
public static final String TABLE_NAME = "student";
public static final String NAME = "name";
public static final String SCORE = "score";
private SQLiteDatabase db;
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
int row = db.delete(TABLE_NAME, selection, selectionArgs);
return row;
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
db.insert(TABLE_NAME, null, values);
Log.e("Test", "insert");
return uri;
}
// 系统自动调用该方法
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
// 创建关系数据库
MySqliteOpenHelper mySqlite = new MySqliteOpenHelper(this.getContext(), TABLE_NAME, null, 1);
//创建表格
db = mySqlite.getWritableDatabase();
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
Cursor cursor = db.query(TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
return cursor;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
int row = db.update(TABLE_NAME, values, selection, selectionArgs);
return row;
}
//数据库创建帮助类
class MySqliteOpenHelper extends SQLiteOpenHelper {
public MySqliteOpenHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
String sql = "create table " + TABLE_NAME
+ " (id integer primary key autoincrement, " + NAME
+ " char(20), " + SCORE + " integer)";
// 执行数据库语言, 创建表格
db.execSQL(sql);
Log.e("Test", "创建表格");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
}
2.Android进程与多线程
[1]一个android应用程序运行在一个独立的进程中,运行在一个独立的dvk中,拥有独立的Linux user id。
android进程的名字为该应用程序的包名
[2]android程序启动后,默认开启一个主线程 (UI线程)
UI线程负责显示界面,负责按键响应,屏幕的触摸响应等。
[3]不能在UI主线程中做耗时的操作。
如果在UI主线程中做耗时的操作,超过5s,系统会报ANR错误。(Application not respond)
如何避免ANR错误,将耗时的操作放在子线程中完成。
[4]耗时的操作:复杂的运算,联网。
[5]Widget控件只能被UI主线程操作,如果子线程操作,会抛出异常。
[6]Handler对象:负责在子线程发送消息 handler.sendMessage(msg)
负责在主线程中接收消息 handlerMessage(Message msg)
将子线程中的计算结果绑定在消息对象 msg.arg1 = count
对消息进行分类 msg.what = 2
package com.farsight.count;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
public class Android_32_CountActivity extends Activity implements
OnClickListener, Runnable {
Button btn;
TextView tv;
boolean isRun;
ArrayList<String> data = new ArrayList<String>();
ArrayAdapter<String> adapter;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(this);
findViewById(R.id.button2).setOnClickListener(this);
findViewById(R.id.button3).setOnClickListener(this);
tv = (TextView) findViewById(R.id.textView1);
ListView listView = (ListView) findViewById(R.id.listView1);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data);
listView.setAdapter(adapter);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (v.getId() == R.id.button1) {
btn.setEnabled(false);
isRun = true;
new Thread(this).start();
} else if (v.getId() == R.id.button2) {
btn.setEnabled(true);
isRun = false;
}else if(v.getId() == R.id.button3){
//每隔2s新增一个item项。
new Thread(new MyRun()).start();
}
}
int countItem;
class MyRun implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
while(countItem < 10){
countItem++;
data.add(String.valueOf(countItem));
//参数 what 表示消息类型
handler.sendEmptyMessage(2);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
int count = 0;
@Override
public void run() {
// TODO Auto-generated method stub
while (isRun) {
count++;
// tv.setText(String.valueOf(count));
//在子线程中发送消息
Message msg = handler.obtainMessage();
//将count值赋值给消息对象
msg.arg1 = count;
msg.what = 1; //给当前消息设置类型
handler.sendMessage(msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
MyHandler handler = new MyHandler();
class MyHandler extends Handler{
//当主线程收到消息时,自动调用该方法
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
//what 表示消息的种类
if(msg.what == 2){
adapter.notifyDataSetChanged();
}else if(msg.what == 1){
int count = msg.arg1;
tv.setText(String.valueOf(count));
}
}
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
isRun = false;
}
}
2.异步任务 AsynicTask
[1]概念:是对Handler机制的高度封装
[2]Handler模式和AsyncTask模式的对比:
Handler模式为每一个任务创建了一个新线程,任务完成后通过handler对象向UI主线程发送消息,完成界面的更新。
这种方式对于整个过程的控制比较精细,但是也有缺点,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确控制。
为了简化操作,使用AsyncTask对Handler机制进行封装。
[3]注意:1.异步任务对象必须在UI主线程中创建
2.不能手动调用异步任务中的方法 doInBackground方法。
3.不能再doInBackground方法中,操作widget控件,因为该方法被子线程调用。
4.一个异步任务对象,只能执行一次。
package com.farsight.asynctask;
import java.util.ArrayList;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class Android_33_AsynicTaskActivity extends Activity implements
OnClickListener {
MyTask task;
ArrayList<String> data = new ArrayList<String>();
ArrayAdapter<String> adapter;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.button1).setOnClickListener(this);
findViewById(R.id.button2).setOnClickListener(this);
findViewById(R.id.button3).setOnClickListener(this);
TextView tv = (TextView) findViewById(R.id.textView1);
task = new MyTask(tv);
ListView listView = (ListView) findViewById(R.id.listView1);
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, data);
listView.setAdapter(adapter);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (v.getId() == R.id.button1) {
// 启动异步任务,开启计数器
task.setRun(true);
task.execute();
} else if (v.getId() == R.id.button2) {
task.setRun(false);
} else if (v.getId() == R.id.button3) {
new AsyncTask<Integer, Integer, Void>() {
@Override
protected Void doInBackground(Integer... params) {
// TODO Auto-generated method stub
int count = 0;
while (count < params[0]) {
count++;
publishProgress(count);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
protected void onProgressUpdate(Integer... values) {
int count = values[0];
data.add(String.valueOf(count));
adapter.notifyDataSetChanged();
}
}.execute(10);
}
}
}
package com.farsight.asynctask;
import android.os.AsyncTask;
import android.widget.TextView;
//Params 启动异步任务的输入参数类型
//Progress 异步任务执行的进度
//Result 异步任务的结果
public class MyTask extends AsyncTask<Void, Integer, Void> {
private TextView tv;
private boolean isRun;
public MyTask(TextView tv) {
// TODO Auto-generated constructor stub
this.tv = tv;
}
//用户启动异步任务时,自动调用该方法
//该方法被子线程调用,用户可以将耗时的操作放在里面
@Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
int count = 0;
while(isRun){
count++;
//发布进度,系统自动调用onProgressUpdate方法,更新进度
publishProgress(count);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
//更新进度
//该方法被UI主线程调用
@Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
int count = values[0];
tv.setText(String.valueOf(count));
super.onProgressUpdate(values);
}
public void setRun(boolean isRun) {
this.isRun = isRun;
}
}