[转载]菜鸟的Android 学习笔记 之四大组件总结

[转载]菜鸟的Android 学习笔记 之四大组件总结 – 行者,无疆 – 博客园.

Activity :

activity是Android提供的界面,所有和用户交互的事情都发生在这个类。

Activity的生命周期:

OnCreate() 创建的时候会调用这个方法 设置这个Activity设置布局控件,初始化数据等。

OnStart() 当控件被我们看到的时候,就调用OnStart()方法 在OnCreate()之后 或者OnStop()后调用。

OnResume() 当重新获得用户焦点的时候就调用这个方法。

onPause() 保护现场用的 可能被另外一个透明的Dialog窗口覆盖,失去焦点,但是他仍然和窗口管理器保持连接,系统可以继续保护Activity的内部状态。

onStop()  停止和OnStart()对应,注意OnStop()和OnPause()不一样的地方是他是完全被另外一个窗口覆灭。也就是失去焦点而且不可见。

onDestory()销毁

创建一个Activity的要点

1.一个Activity就是一个类,并且这个类要继承Activity

2.需要复写onCreate方法

3.要在Androidmanifest.xml进行配置(四大组件都要进行配置)

4.为Activity添加必要的控件

在一个Activity启动另外一个Activity

Intent intent=new Intent(CurrentActivity.this,OtherActivity.class) //OtherActivity也要在AndroidManifest.xml中注册。

startActivity(intent);

Intent还可以放入各种数据 传入下一个Activity。

可以用下面的方式接收传过来的数据:

还可以用Bundel的方法发送数据。Bundel就像一个承载数据的List<> 里面可以放各种数据。但是他的key只能是string类型的,放入Intent的方式也是intent.putExtra(bundle);

Service

Service在什么时候会用到呢?比如说音乐程序的时候,需要后台运行,但是又看不到界面,此时就用到Service。这也是Service和Activity最大的不同。

Service 分类:

本地Service和远程Service。

本地Service是同一个进程内Service彼此之间共同的内存区域。

远程Service是同一个系统内的不同进程之间访问(注意是同一个系统内,不是不同系统)。

Service生命周期:

onCreate()->onStart()->onDestory() 三个方法 继承的时候如果要用到记得重新写下。

创建一个Service要点:

1.  创建一个类,要继承Service

2.  要在androidManifest.xml中进行配置

3.  在Activity中配置调用它

Broadcast Receiver

在android中可以通过broadcast告诉其他程序发生了什么事情。比如电源,比如短信,比如信号。

Broadcast Receiver相比于其他组件比较特别的地方是他还提供了一种所谓的热注册,就是不用写在androidManifest.xml中,直接用

registerReceiver(Broadcastreceiver,IntentFilter)注册。然后用unregisterReceiver()消除注册。

一些常用的Action:

ACTION_CALL                                              activity                        启动一个电话.
ACTION_EDIT                                               activity                       显示用户编辑的数据.
ACTION_MAIN                                               activity                      作为Task中第一个

Activity启动
ACTION_SYNC                                             activity                         同步手机与数据服务器上的数据.
ACTION_BATTERY_LOW                           broadcast receiver       电池电量过低警告.
ACTION_HEADSET_PLUG                        broadcast receiver        插拔耳机警告
ACTION_SCREEN_ON                               broadcast receiver        屏幕变亮警告.
ACTION_TIMEZONE_CHANGED              broadcast receiver         改变时区警告.

Content Provider

这个组件比较复杂

ContentProvider可以支持多个应用的数据共享。可以用来操作音频,视频,图片,私人通讯录等等。但是要记得获取适当的读取权限。当然也可以用来公开自己的数据。(难道Content Provider是全局变量?整个手机的程序都能访问得到?)

创建Content Provider 要点:

1.  创建一个Content Provider首先要继承ContentProvider类。

2.       在androidManifest中配置

3.       在Activity类中调用insert() query()可以调用

实际上所有的contentprovider用户都不能直接访问contentprovider实例,只能通过ContentResolver的中 间代理。而要得到ContentResolver的实例可以用Activity的getContentResolver方法。如下

可以自己去调用ContentProvider相应的方法。

Uri使用方法:来自http://blog.sina.com.cn/s/blog_5688414b0100xagp.html

一、Content Provider基本概念

1、ContentProvider为存储和获取数据提供了统一的接口。ContentProvide对数据进行封装,不用关心数据存储的细节。使用表的形式来组织数据。

Android学习十九:ContentProvider初步

2、使用ContentProvider可以在不同的应用程序之间共享数据。

3、Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。

ContentProvider所提供的函数:

query(),insert(),update(),delete(),getType(),onCreate()等。

二、URI统一资源标识符)的使用方法

为系统的每一个资源给其一个名字,比方说通话记录。

1、每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。

2、Android所提供的ContentProvider都存放在android.provider包中。 将其分为A,B,C,D 4个部分:

Android学习十九:ContentProvider初步

A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;”content://”

B:URI 的标识,它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的 类名。这个标识在 元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称;”content://hx.android.text.myprovider”

C:路径,不知道是不是路径,通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就ok了;”content://hx.android.text.myprovider/tablename”

D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部; “content://hx.android.text.myprovider/tablename/#” #表示数据id

三、ContentProvider的实现过程

自己实现ContentProvider不常见,因为可能不需要和别的应用程序交换数据。使用内置的ContentProvider比较多。

1、定义一个CONTENT_URI常量,提供了访问ContentProvider的标识符。

public static final Uri CONTENT_URI = Uri.parse("content://com.example.codelab.transportationprovider");

其中:content是协议

Com.exmaple.codelab.transportationprovider是类名,包含完整的包名。

Uri.parse将一个字符串转换成Uri类型。

如果Provider包含子表,同样定义包含字表的CONTENT_URI。

content://com.example.codelab.transportationprovider/train
content://com.example.codelab.transportationprovider/air/domestic
content://com.example.codelab.transportationprovider/air/international

然后定义列,确保里面包含一个_id的列。

2、定义一个类,继承ContentProvider。

public class FirstContentProvider extends ContentProvider

先介绍一下ContentProvider用到的UriMatcher。UriMatcher的一个重要的函数是match(Uri uri)。这个函数可以匹配Uri,根据传入的不同Uri返回不同的自定义整形值,以表明Uri访问的不同资源的类型。

例如:

      public static final UriMatcher uriMatcher;
      static {
                     uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
                     uriMatcher.addURI(Book.AUTHORITY, "item", Book.ITEM);
                     uriMatcher.addURI(Book.AUTHORITY, "item/#", Book.ITEM_ID);
              }

这里UriMatcher类型的静态字段是用来匹配传入到ContentProvider中的Uri的类。其构造方法传入的匹配码是使用match()方法匹配根路径时返回的值,这个匹配码可以为一个大于零的数表示匹配根路径或传入-1,即常量UriMatcher.NO_MATCH表示不匹配根路径。 addURI()方法是用来增加其他URI匹配路径的,第一个参数传入标识ContentProvider的AUTHORITY字符串。第二个参数传入需要匹配的路径,这里的#号为通配符,代表匹配任意数字,另外还可以用*来匹配任意文本。第三个参数必须传入一个大于零的匹配码,用于match()方法对相匹配的URI返回相对应的匹配码。 例如:sMatcher.addURI(“com.test.provider.personprovider”, “person”, 1);如果match()方法匹配content://com.test.provider.personprovider/person路径,返回匹配码为1。

3、实现query,insert,update,delete,getType和onCreate方法。

4、在AndroidManifest.xml当中进行声明。

<!-- android:name是完成ContentProvider类的全称
             android:authorities是和FirstProvidermetaData中的常量AUTHORITY的值一样,否则会报错
         -->
        <provider android:name="com.bj.FirstContentProvider"
            android:authorities="com.bj.firstcontentprovider"
            />

四、具体代码

Activity19Activity.java

public class Activity19Activity extends Activity {

private Button queryButton = null;

private Button insertButton = null;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

queryButton = (Button) this.findViewById(R.id.query);

queryButton.setOnClickListener(newQueryListener());

insertButton = (Button) this.findViewById(R.id.insert);

insertButton.setOnClickListener(newInsertListener());

System.out.println(getContentResolver().getType(FirstProvidermetaData.UserTableMetaData.CONTENT_URI));

}

class InsertListener implementsOnClickListener {

@Override

public void onClick(View v) {

// TODOAuto-generated method stub

ContentValues values = new ContentValues();

values.put(FirstProvidermetaData.UserTableMetaData.USER_NAME,

“michal”);

Uri uri = getContentResolver()

.insert(

FirstProvidermetaData.UserTableMetaData.CONTENT_URI,

values);

System.out.println(“uri—>” + uri.toString());

}

}

class QueryListener implementsOnClickListener {

public void onClick(View v) {

Cursor c = getContentResolver().query(

FirstProvidermetaData.UserTableMetaData.CONTENT_URI, null,

null, null, null);

while (c.moveToNext()) {

System.out.println(c.getString(c.getColumnIndex(“username”)));

}

}

}

}

FirstContentProvider.java

public class FirstContentProvider extendsContentProvider {

// 当别的程序来访问这个ContentProvider,是通过Uri来访问的,UriMatcher检查是否符合标准

// uri起一个规则,返回数字

public static final UriMatcher uriMatcher;

// 下面定义两个规则

public static final int INCOMING_USER_COLLECTION = 1;

public static final int INCOMING_USER_SINGLE = 2;

private DatabaseHelper dh;

static {//下面的users前面不能加/

uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

uriMatcher.addURI(FirstProvidermetaData.AUTHORITY, “users”,

INCOMING_USER_COLLECTION);

uriMatcher.addURI(FirstProvidermetaData.AUTHORITY, “users/#”,

INCOMING_USER_SINGLE);

}

//有点类似于SQL里面表的别名,这个也是给列其别名,必须要用

//列的别名还是原来的名,没必要修改

public static HashMap<String,String> userProjectionMap;

static{

userProjectionMap = newHashMap<String,String>();

userProjectionMap.put(UserTableMetaData._ID, UserTableMetaData._ID );

userProjectionMap.put(UserTableMetaData.USER_NAME, UserTableMetaData.USER_NAME);

}

@Override

public int delete(Uri uri, String selection, String[] selectionArgs) {

// TODOAuto-generated method stub

System.out.println(“delete”);

return 0;

}

// 根据传入的URI,返回该URI所表示的数据类型

// 也就是说,我们通过URI要访问的数据,返回什么类型

@Override

public String getType(Uri uri) {

// TODOAuto-generated method stub

System.out.println(“getType”);

switch (uriMatcher.match(uri)) {

case INCOMING_USER_COLLECTION:

// UserTableMetaDataFirstProvidermetaData的内部类

return UserTableMetaData.CONTENT_TYPE;

case INCOMING_USER_SINGLE:

return UserTableMetaData.CONTENT_TYPE_ITEM;

default:

throw new IllegalArgumentException(“Unknown uri” + uri);

}

}

@Override

public Uri insert(Uri uri, ContentValues values) {

// TODOAuto-generated method stub

System.out.println(“insert”);

SQLiteDatabase db = dh.getWritableDatabase();

//返回表中自动增长的列的值,否则返回-1

long rowId = db.insert(UserTableMetaData.TABLE_NAME,null, values);

if(rowId>0){

//rowId追加到后面

//contentUris:用来处理Uri的工具类

Uri insertedUserUri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId);

//通知监听器,数据已经改变

getContext().getContentResolver().notifyChange(insertedUserUri, null);

return insertedUserUri;

}

throw new SQLException(“Failed to insert row into “+uri);

}

//是一个回调方法,所以说在ContentProvider创建的时候执行

//也就是创建这个DatabaseHelper对象

@Override

public boolean onCreate() {

// TODOAuto-generated method stub

//getContext得到当前正在运行着的context

dh = new DatabaseHelper(getContext(),FirstProvidermetaData.DATABASE_NAME);

System.out.println(“on create”);

SQLiteDatabase db = dh.getReadableDatabase();

return true;

}

//projection:查询的列有哪些

//selection:where子句的内容,可以用?

//selectionArgs:占位符对应的参数

//sortOrder:排序

@Override

public Cursor query(Uri uri, String[] projection, String selection,

String[] selectionArgs, String sortOrder) {

// TODOAuto-generated method stub

System.out.println(“query”);

//创建一个查询的语句

SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

switch(uriMatcher.match(uri)){

case INCOMING_USER_COLLECTION:

//设置查询哪张表

qb.setTables(UserTableMetaData.TABLE_NAME);

qb.setProjectionMap(userProjectionMap);

break;

case INCOMING_USER_SINGLE:

qb.setTables(UserTableMetaData.TABLE_NAME);

qb.setProjectionMap(userProjectionMap);

//添加where条件,getPathSegments:得到uripath部分content:XXX/user/1get(1)得到1

qb.appendWhere(UserTableMetaData._ID+”=”+uri.getPathSegments().get(1));

break;

}

String orderBy;

if(TextUtils.isEmpty(sortOrder)){

orderBy = UserTableMetaData.DEFAULT_SORT_ORDER;

}

else

{

orderBy = sortOrder;

}

SQLiteDatabase db = dh.getWritableDatabase();

//下面的query使用qb这个对象

Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);

//也是通知下

c.setNotificationUri(getContext().getContentResolver(), uri);

System.out.println(“query”);

return c;

}

@Override

public int update(Uri uri, ContentValues values, String selection,

String[] selectionArgs) {

// TODOAuto-generated method stub

return 0;

}

}

FirstProvidermetaData.java

public class FirstProvidermetaData {

public static final String AUTHORITY=”com.bj.firstcontentprovider”; //继承了contentprovider的类的全名

//数据库名称

public static final String DATABASE_NAME = “FirstProvider.db”;

//数据库的版本

public static final int DATABASE_VERSION = 1;

//表名

public static final String USERS_TABLE_NAME = “users”;

public static final class UserTableMetaData implements BaseColumns{

//表名

public static final String TABLE_NAME=”users”;

//访问该ContentProviderURI

public static final Uri CONTENT_URI=Uri.parse(“content://”+AUTHORITY+”/users”);

public static final String CONTENT_TYPE=”vnd.android.cursor.dir/vnd.firstprovider.user”;

public static final String CONTENT_TYPE_ITEM=”vnd.android.cursor.item/vnd.firstprovider.user”;

//列名,在users表中添加一个名为name的列

public static final String USER_NAME=”name”;

//默认排序方式

public static final String DEFAULT_SORT_ORDER=”_id desc”;

}

}

DatabaseHelper.java见Android学习十六:SQLite使用方法

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏