您的位置:首页 > 移动开发 > Android开发

Android四大组件之三:ContentProvider数据共享

2015-08-09 20:43 567 查看
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;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: