显示:所有子控件按照横向或者竖向依次排列,
属性:
android:orientation=“vertical”(竖向),android:orientation=“horizontal”(横向)。
orientation:布局中组件的排列方式,有horziontal(水平)和vertical(垂直)两种方式。
layout_width:布局的宽度,通常不直接写数字,用wrap_content(组件实际大小),fill_parent或者match_parent填满父容器。
layout_height:布局的高度,参数同上。
id:为该组件设置一个资源id,在java文件中可以通过findViewByid(id)找到该组件。
background:为该组件设置一个背景图片,或者直接用颜色覆盖。
gravity:控制组件所包含的子元素的对齐方式,可多个组合,如(left|buttom)。
layout_gravity:控制该组件在父容器里的对齐方式。
显示:所有子控件默认显示在RelativeLayout的左上角
属性:
gravity:设置容器内组件的对齐方式
ignoreGravity:设置了属性为true属性的组件,将不受gravity属性的影响
显示:所有子控件默认在GridLayout中横向依次排列,当只等每行的列数时,到达指定列数会自动换行显示。
属性:
layout_column 在网格的第几列
layout_row 在网格的第几行
layout_columnSpan 跨列
layout_rowSpan 跨行
layout_gravity 在一个网格中的重心位置
columnCount 每行列总数
显示:所有的子控件默认显示在FrameLayout的左上角,会重叠在一起显示。
属性:
foreground:用来设置帧布局容器的前景图像。
foregroundGravity:用来设置帧布局容器的前景图像显示的位置。
后期补
作用: 文本展示
属性:
//控件id
android:id = "@+id/xxx" @+id/xxx表示新增控件命名为xxx
//宽度与高度
android:layout_width="wrap_content" //wrap_content或者match_parent
android:layout_height="wrap_content" //wrap_content或者match_parent
//文本文字
android:text="@string/hello_world" //两种方式,直接具体文本或者引用values下面的string.xml里面的元素
//字体大小
android:textSize="24sp" //以sp为单位
//字体颜色
android:textColor="#0000FF" //RGB颜色
//字体格式
android:textStyle="normal" //normal,bold,italic分别为正常,加粗以及斜体,默认为normal
//文本显示位置
android:gravity="center" //来指定文字的对齐方式,可选值有 top、bottom、left、right、center 等
//是否只在一行内显示全部内容
android:singleLine="true" //true或者false,默认为false
拓展: shape文件,定义控件展示效果
作用: 按钮
属性:
//控件id
android:id = "@+id/xxx" @+id/xxx表示新增控件命名为xxx
//宽度与高度
android:layout_width="wrap_content" //wrap_content或者match_parent
android:layout_height="wrap_content" //wrap_content或者match_parent
//按钮上显示的文字
android:text="theButton" //两种方式,直接具体文本或者引用values下面的string.xml里面的元素@string/button
//按钮字体大小
android:textSize="24sp" //以sp为单位
//字体颜色
android:textColor="#0000FF" //RGB颜色
//字体格式
android:textStyle="normal" //normal,bold,italic分别为正常,加粗以及斜体,默认为normal
//是否只在一行内显示全部内容
android:singleLine="true" //true或者false,默认为false
//保存指定的原始文字内容,如英文字母小写
android:textAllCaps="false" //true或者false,默认为true
拓展 : 根据不同的状态,设置不同的背景效果
以按钮背景引入,item 标签设置状态
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 1、正常状态-->
<item android:drawable="@color/green" />
<!-- 2、是否获得焦点-->
<item android:state_focused="true" />
<!-- 3、是否获得窗口焦点-->
<item android:state_window_focused="true" />
<!--4、是否可用-->
<item android:state_enabled="true" />
<!-- 5、可是否勾选-->
<item android:state_checkable="true" />
<!-- 6、是否被勾选-->
<item android:state_checked="true" />
<!--7、是否被选择,有滚轮的情况-->
<item android:state_selected="true" />
<!-- 8、是否被按下-->
<item android:drawable="@color/red" android:state_pressed="true" />
<!-- 9、是否处于活跃状态-->
<item android:state_active="true" />
<!-- 10、多个子控件,仅显示一个/first/中间/last-->
<item android:state_single="true" />
<item android:state_first="true" />
<item android:state_middle="true" />
<item android:state_last="true" />
</selector>
几种写法
①匿名内部类
②定义内部类,实现OnClickListender接口
③用activity实现OnClickListender接口
④指定button的OnClick属性
作用: 输入框,可编辑
属性:
//控件id
android:id = "@+id/xxx" @+id/xxx表示新增控件命名为xxx
//宽度与高度
android:layout_width="wrap_content" //wrap_content或者match_parent
android:layout_height="wrap_content" //wrap_content或者match_parent
//文本文字
android:text="@string/hello_world" //两种方式,直接具体文本或者引用values下面的string.xml里面的元素
//文本提示内容
android:hint="hello_world" //android:text和android:hint区别是后者只是提示作用,真正需要输入的时候提示的内容会消失
//字体大小
android:textSize="24sp" //以sp为单位
//字体颜色
android:textColor="#0000FF" //RGB颜色
//默认提示文本颜色
android:textColorHint="@color/green"
//字体格式
android:textStyle="normal" //normal,bold,italic分别为正常,加粗以及斜体,默认为normal
//文本显示位置
android:gravity="center" //来指定文字的对齐方式,可选值有 top、bottom、left、right、center 等
//是否只在一行内显示全部内容
android:singleLine="true" //true或者false,默认为false
//输入内容设置为password类型
android:password="true" //输入的内容会变成······
//输入内容设置为phoneNumber类型
android:phoneNumber="true" //只能输入数字
//对输入内容进行限制,可选值number,text......
android:inputType="number"
//指定最大行数,超过时文本会向上滚动
android:maxLines="3"
//设置最小行
android:minLines="2"
//只允许单行输入,且不滚动
android:selectAllOnFocus="true"
//点击输入框获取焦点,即选中所有内容(首次)
android:selectAllOnFocus="true"
//设置字与字水平间隔
android:textScaleX="1.2"
//设置字与字垂直间隔
android:textScaleY="1.2"
//设置字母大小写,可选值characters(仅第一个字母大写),words(每一个首字母大写),characters(全部大写)
android:capitalize="characters"
//设定光标为显示/隐藏
android:cursorVisible = "false" //true或者false,默认为true显示
拓展:
获得或失去焦点
editText.requestFocus();
or
editText.clearFocus()
光标位置的控制
作用: ImageView控件负责显示图片,其图片的来源可以是在资源文件中的id,也可以是Drawable对象或者位图对象。还可以是Content Provider的URI
属性:
<ImageView
//控件id
android:id = "@+id/xxx" @+id/xxx表示新增控件命名为xxx
//宽度与高度
android:layout_width="wrap_content" //wrap_content或者match_parent
android:layout_height="wrap_content" //wrap_content或者match_parent
//此外,可以具体设置高度和宽度显示的像素,不过这样设置如果图片尺寸大于设置的显示的尺寸,则图片是显示不全的,这是可以配合android:scaleType属性。
android:layout_width="200dp"
android:layout_height="200dp"
//android:scaleType属性,因为关于图像在ImageView中的显示效果,所以有如下属性值可以选择:
matrix:使用matrix方式进行缩放。
fitXY:横向、纵向独立缩放,以适应该ImageView;
fitStart:保持纵横比缩放图片,并且将图片放在ImageView的左上角;
fitCenter:保持纵横比缩放图片,缩放完成后将图片放在ImageView的中央;
fitEnd:保持纵横比缩放图片,缩放完成后将图片放在ImageView的右下角;
center:把图片放在ImageView的中央,但是不进行任何缩放;
centerCrop:保持纵横比缩放图片,以使图片能完全覆盖ImageView;
centerInside:保持纵横比缩放图片,以使得ImageView能完全显示该图片;
//图片来源,需要将图片复制放到res/drawable文件夹里面,引用的时候不需要写图片的后缀
android:src ="@drawable/beautiful">
android:background="@drawable/pikachu"
以上两者的区别
src属性,给ImageView指定一张图片,按图片大小填充内容,不会拉伸,代码中使用mImgs.setImageDrawable()设置src属性
background属性,填入照片,会根据ImageView给定的宽度进行拉伸,代码中使用mImgs.setBackgroundDrawable()设置background属性
作用: ProgressBar 用于在界面上显示一个进度条,表示我们的程序正在加载一些数据,运行程序,会看到屏幕中有一个圆形进度条正在旋转。
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100" />
//默认是圆形进度条,可以使用style属性设置为水平进度条;若为水平进度条,使用属性android:max设置最大值,然后在代码中动态地更改进度条的进度。
属性: android:visibility,设置进度条是否可见,可选值visible(可见),invisible(不可见但占据屏幕空间),gone(不可见且不占据空间)
与用户进行交互
(1)自定义Activity类名,继承Activity类或者其他子类
(2)重写onCreate()方法,在方法中调用setContentView()设置要显示的视图
(3)在AndroidMainfest.xml对Activity进行注册
(4)启动Activity:调用startActivity(intent);
**重点
(1)onCreate():在活动第一次被创建的时候调用,用来完成活动的初始化操作,如加载布局、绑定事件等
(2)onStart():在活动由不可见变为可见时被调用
(3)onResume():在活动准备和用户交互的时候被调用。此时的活动一定位于返回栈的栈顶,并且处于运行状态
(4)onPause():在系统准备去启动或者恢复另外一个活动的时候调用。在此方法中将一些消耗CPU的资源释放,以及保存一些关键数据,,但这个方法一定要快,不然会影响到新的栈顶活动的使用
(5)onStop():在活动完全不可用时被调用。和onPause()的区别在于,如果启动一个对话框式的活动,那么onPause()方法会执行,而onStop()不会执行
(6)ondestroy():在活动被销毁之前调用,之后活动的状态将变为销毁态
(7)onRestart():在活动由停止状态变为运行状态之前调用,就是活动被重新启动
1)显示intent
①常用
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
②ComponentName
Button componentBtn = findViewById(R.id.componentIntent);
componentBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
ComponentName comp = new ComponentName(MainActivity.this,SecondActivity.class);
intent.setComponent(comp);
startActivity(intent);
}
}
ComponentName,顾名思义,就是组件名称,通过调用Intent中的setComponent方法,我们可以打开另外一个应用中的Activity或者服务,实例化一个ComponentName需要两个参数,第一个参数是要启动应用的包名称,这个包名称是指清单文件中列出的应用的包名称:
第二个参数是你要启动的Activity或者Service的全称(包名+类名),启动一个Service:
Intent intent = new Intent();
ComponentName comp = new ComponentName("com.example.aidl", "com.example.aidl.MyAidlService");
intent.setComponent(comp);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
③setClass
Intent intent = new Intent();
intent.setClass(MainActivity.this,SecondActivity.class);
//或者
intent.setClassName(MainActivity.this,SecondActivity.class.getName());
//setClassName跳转到不同Applicaiton的activity或者service
//或者
Intent intent1 = new Intent("android.intent.action.MAIN");
intent1.setClassName(MainActivity.this,SecondActivity.class.getName());
startActivity(intent);
2)隐式intent
在AndroidMainfest.xml中配置内容,可以指定当前Activity能够响应的action和category
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="com.example.demo.SecondActivity.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
MainActivity
Intent intent = new Intent("com.example.demo.SecondActivity.ACTION_START");
startActivity(intent);
category是默认的,也可以增加(MainActivity)
intent.addCategory("com.example.demo.SecondActivity.MY_CATEGORY");
同时在AndroidMainfest.xml添加一个category声明
<category android:name="com.example.demo.SecondActivity.MY_CATEGORY" />
(1)Standard模式(标准模式)
在Standard模式下,每当启动一个新的Activity,都会创建一个该Activity的新实例,它就会在返回栈中入栈,且处于栈顶的位置。
应用场景:默认
(2)SingleTop模式(栈顶复用模式)r
若Activity的启动模式为SingleTop,在启动Activity时,会检查返回栈的栈顶是否为该Activity,若是则直接使用,否则创建新的Activity实例。
应用场景:APP接收到多条推送消息,点开不同消息,均由同一实例展示。
(3)SingleTask模式(栈内复用模式)
若Activity的启动模式为SingleTask,在启动Activity时,系统首先会在返回栈中检查是否存在该Activity的实例,若存在则直接使用该实例,并把在这个Activity之上的所有其他Activity统统出栈,若没有则创建一个新的Activity实例。
应用场景:APP的主页,无论哪种业务场景下再次回到此页,都不应保留之上Activity,如浏览器,微博等。
(4)SingleInstance模式(单一实例模式)
若Activity的启动模式为SingleInstance,会启动一个新的返回栈来管理这个Activity。每个应用程序都有自己的返回栈,同一个Activity在不同的返回栈中入栈时必然创建了新的实例;在此种模式下,会有一个单独的返回栈来管理这个Activity,不管哪个应用程序来访问这个Activity,都共用同一个返回栈,也就解决了共享Activity实例的问题。
应用场景:APP经常调用的拨打电话、系统通讯录、地图类APP 等页面,不同APP调用此类Activity 时,首次创建实例,之后其他APP只能复用此实例。
拓展
http://t.csdn.cn/pnY4c
1)向下一个Activity传递数据
①使用Intent的putExtra传递
/*第一个Activity*/
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
//设置传递键值对
intent.putExtra("name", "独爱空城梦");
startActivity(intent);
/*第二个Activity*/
// 获取意图对象
Intent intent = getIntent();
String result = intent.getStringExtra("name");
mText.setText(result);
②使用Intention的Bundle传递
Bundle主要用于传递数据;它保存的数据,是以key-value(键值对)的形式存在的。
Bundle经常使用在Activity之间或者线程间传递数据,传递的数据可以是boolean、byte、int、long、float、double、string等基本类型或它们对应的数组,也可以是对象或对象数组。
当Bundle传递的是对象或对象数组时,必须实现Serializable 或Parcelable接口。
Bundle提供了各种常用类型的putXxx()/getXxx()方法,用于读写基本类型的数据。
Bundle使用有3种情况,分别为在activity间传递信息,线程间传递信息和使用序列化Seriazable时使用Bundle对象,如下:
a.在activity中传递
/* 第一个Activity中*/
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
//用数据捆传递数据
Bundle bundle = new Bundle();
bundle.putString("name", "沙漏的心");
//把数据捆设置给意图
intent.putExtra("bund", bundle);
startActivity(intent);
/* 第二个Activity中*/
// 获取意图对象
Intent intent = getIntent();
Bundle bundle = intent.getBundleExtra("bund");
String result = bundle.getString("name");
mText.setText(result);
b.线程间传递
c.使用序列化对象Seriazable
(后续补上)
特点:
①Fragment是依赖于Activity的,不能独立存在的。
②一个Activity里可以有多个Fragment,而一个Fragment可以被多个Activity重用。
③Fragment有自己的生命周期,并能接收输入事件。
④能在Activity运行时动态地添加或删除Fragment。
• onAttach():Fragment和Activity相关联时调用。可以通过该方法获取Activity引用,还可以通过getArguments()获取参数。
• onCreate():Fragment被创建时调用。
• onCreateView():创建Fragment的布局。
• onActivityCreated():当Activity完成onCreate()时调用。
• onStart():当Fragment可见时调用。
• onResume():当Fragment可见且可交互时调用。
• onPause():当Fragment不可交互但可见时调用。
• onStop():当Fragment不可见时调用。
• onDestroyView():当Fragment的UI从视图结构中移除时调用。
• onDestroy():销毁Fragment时调用。
• onDetach():当Fragment和Activity解除关联时调用。
fragment生命周期解析:
当一个fragment被创建的时候,需调用以下生命周期方法:onAttach(), onCreate(), onCreateView(), onActivityCreated()
当这个fragment对用户可见的时候,需调用:onStart() ,onResume()
当这个fragment进入后台模式需调用:onPause(),onStop()
当这个fragment被销毁或者是持有它的Activity被销毁了,调用:onPause() ,onStop(), onDestroyView(), onDestroy() onDetach()
(1)静态加载
流程
①定义Fragment的xml布局文件
②自定义Fragment类,继承Fragment,重写onCreateView()方法,并加载布局文件
③在需要加载的xml布局文件中,使用fragment标签的name属性指定要加载的Fragment,即Fragment的全限定类名
④Activity在加载布局
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_front, container, false);
return view;
}
/* xml中*/
android:name="com.example.project.fragment.FirstFragment"
(2)动态加载
流程
①创建待添加的Fragment实例
②获得FragmentManager对象,通过getSupportFragmentManager()
③开启事务使用beginTransaction()加载
④调用add()方法或者replace()方法Fragment,需要传入两个参数,传入容器的id和待添加的Fragment实例
⑤提交事务,调用commit()方法
SecondFragment fragment = new SecondFragment();
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transition = manager.beginTransaction();
transition.add(R.id.linear, fragment);
transition.commit();
1.数据传递
(1)Activity向Fragment传递数据
①在Activity中传出,使用setArguments()方法
SecondFragment fragment = new SecondFragment();
Bundle bundle = new Bundle();
bundle.putString("name", "ag");
fragment.setArguments(bundle);
②在Fragment中接收,使用getArguments()方法
Bundle bundle = getArguments();
mTextSe.setText(bundle.getString("name"));
(2)Fragment向Activity传递数据,使用回调接口,在Fragment中定义一个内部回调接口,再让包含该Fragment的Activity实现该回调接口,实现两者之间的通信
①定义一个回调接口:(Fragment中)
// 定义回调接口
public interface CallBack {
// 定义一个获取信息的方法
public void getResult(String result);
}
②接口回调(Fragment中)
// 调用接口
public void getData(CallBack callBack) {
String msg = "我是Fragment传递给Activity的值";
callBack.getResult(msg);
}
③使用接口回调方法读数据(Activity中)
2.组件获取
Fragment获取Activity中的组件: getActivity().findViewById(R.id.textTop);
Fragment获取Fragment中的组件getFragmentManager().findFragmentByTag(R.id.test);
viewpager有三个适配器,pagerAdapter,FragmentpagerAdapter,FragmentStatePagerAdapter。
(1)pagerAdapter是普通的pager适配器,操作方便,结构和功能大概和recyclerView的适配器类似;
(2)FragmentPagerAdapter是用于碎片的适配器,这个适配器相比第三种FragmentStatePagerAdapter来说,更适合界面少的情况,因为这个适配器会缓存当前页面在内的左右共三个界面,实现快速展示,但是界面多的时候则会占用大部分资源;
(3)当使用FragmentStatePagerAdapter 时,实现将只保留当前页面,当页面离开视线后,就会被消除,释放其资源;而在页面需要显示时,生成新的页面。这么实现的好处就是当拥有大量的页面时,不必在内存中占用大量的内存。
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> mList;
public ViewPagerAdapter(FragmentManager fm, List<Fragment> list) {
super(fm);
mList = list;
}
@Override
public Fragment getItem(int position) {
return mList.get(position);
}
@Override
public int getCount() {
return mList.size();
}
}
adapter是view和数据的桥梁
(1)BaseAdapter+ListView最基本的方法:
public int getCount(): 适配器中数据集的数据个数;
public Object getItem(int position): 获取数据集中与索引对应的数据项;
public long getItemId(int position): 获取指定行对应的ID;
public View getView(int position,View convertView,ViewGroup parent): 获取每一行Item的显示内容。
(2)ListView加载不同布局
①增加Type
②重写getViewTypeCount方法
③重写getItemViewType方法
④重写getView方法
扩展:
点击不同item,携带参数跳转到百度并搜索
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Uri uri = Uri.parse("http://baike.baidu.com/" + mList.get(position).getName());
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
});
service是一种可以在后台执行长时间运行操作而没有用户界面的应用组件。服务可由其他应用组件启动(activity),服务一旦启动将在后台一直运行,即使启动服务的组件(activity)已销毁也不影响。此外组件可以绑定到服务,以与之进行交互,甚至是执行进程间通讯(IPC)。
a.Service启动状态
当应用组件(如 Activity)通过调用 startService() 启动服务时,服务即处于“启动”状态。一旦启动,服务即可在后台无限期运行,即使启动服务的组件已被销毁也不受影响,除非手动调用才能停止服务, 已启动的服务通常是执行单一操作,而且不会将结果返回给调用方。
首次启动会创建一个Service实例,依次调用onCreate()和onStartCommand()方法,此时Service 进入运行状态,如果再次调用StartService启动Service,将不会再创建新的Service对象, 系统会直接复用前面创建的Service对象,调用它的onStartCommand()方法!
b.Service绑定状态
当应用组件通过调用 bindService() 绑定到服务时,服务即处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。 仅当与另一个应用组件绑定时,绑定服务才会运行。 多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。
当首次使用bindService绑定一个Service时,系统会实例化一个Service实例,并调用其onCreate()和onBind()方法,然后调用者就可以通过IBinder和Service进行交互了,此后如果再次使用bindService绑定Service,系统不会创建新的Sevice实例,也不会再调用onBind()方法,只会直接把IBinder对象传递给其他后来增加的客户端!
如果我们解除与服务的绑定,只需调用unbindService(),此时onUnbind和onDestory方法将会被调用!这是一个客户端的情况,假如是多个客户端绑定同一个Service的话,当一个客户完成和service之间的互动后,它调用 unbindService() 方法来解除绑定。当所有的客户端都和service解除绑定后,系统会销毁service。
Service生命周期图,如下所示:
——onCreate():当Service第一次被创建后立即回调该方法,该方法在整个生命周期 中只会调用一次!
——onDestory():当Service被关闭时会回调该方法,该方法只会回调一次!
——onStartCommand(intent,flag,startId):当客户端调用startService(Intent)方法时会回调,可多次调用StartService方法, 但不会再创建新的Service对象,而是继续复用前面产生的Service对象,但会继续回调 onStartCommand()方法!
——IBinder onOnbind(intent):该方法是Service都必须实现的方法,该方法会返回一个 IBinder对象,app通过该对象与Service组件进行通信!
——onUnbind(intent):当该Service上绑定的所有客户端都断开时会回调该方法!
StartService启动Service后bindService绑定
如果Service已经由某个客户端通过StartService()启动,接下来由其他客户端 再调用bindService()绑定到该Service后调用unbindService()解除绑定最后在 调用bindService()绑定到Service的话,此时所触发的生命周期方法如下:
onCreate( )->onStartCommand( )->onBind( )->onUnbind( )->onRebind( )
结论:使用bindService来绑定一个启动的Service,注意是已经启动的Service!!! 系统只是将Service的内部IBinder对象传递给Activity,并不会将Service的生命周期 与Activity绑定,因此调用unBindService( )方法取消绑定时,Service也不会被销毁!
1.Hander
2.AsyncTask
3.Binder机制
4.AIDL
详见专栏Android中 数据库
ContentProvider(内容提供者)是Android中的四大组件之一。主要用于对外共享数据,也就是通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider对指定应用中的数据进行操作。
Android提供了一些主要数据类型的ContentProvider,比如音频、视频、图片和私人通讯录等。
主要重写方法:
1】onCreate(),创建和升级数据库,仅当ContentResolver尝试访问我们程序中的数据时,内容提供器才会被初始化
2】query(),查询表中数据,参数Uri指那张表,查询结果存放再Cursor对象中
3】insert(),添加数据,待添加数据存放在values参数中。添加后返回这条新纪录的Uri
4】update(),更新数据,返回结果为更新行数
5】delete(),删除数据,返回结果为删除行数
6】getType(),根据传入的内容Uri来返回相应的MIME类型
public boolean onCreate() 在创建ContentProvider时调用
public Cursor query(Uri, String[], String, String[], String) 用于查询指定Uri的ContentProvider,返回一个Cursor
public Uri insert(Uri, ContentValues) 用于添加数据到指定Uri的ContentProvider中
public int update(Uri, ContentValues, String, String[]) 用于更新指定Uri的ContentProvider中的数据
public int delete(Uri, String, String[]) 用于从指定Uri的ContentProvider中删除数据
public String getType(Uri) 用于返回指定的Uri中的数据的MIME类型
通配符:*:表示匹配任意长的的任意字符,#:表示匹配任意长度的数字
UriMatcher实现匹配内容Uri功能,提供方法addURI(),3个参数authority,path和自定义代码;这样,当调用UriMatcher的match()方法时,就可以将一个Uri对象传入,返回值是某个能够匹配这个Uri对象所定义的自定义代码,根据这个自定义代码,可以判断出调用方期望访问哪张表中的数据。
public String getType(@NonNull Uri uri) {
switch (mUriMatcher.match(uri)) {
case TABLE1_DIR:
return "vnd.android.cursor.dir/vnd.com.example.android.provider.table1";
case TABLE1_ITEM:
return "vnd.android.cursor.item/vnd.com.example.android.provider.table1";
case TABLE2_DIR:
return "vnd.android.cursor.dir/vnd.com.example.android.provider.table2";
case TABLE2_ITEM:
return "vnd.android.cursor.item/vnd.com.example.android.provider.table2";
default:
break;
}
return null;
}
创建UriMatcher实例。调用addURI(),将期望匹配的内容Uri传递进去
MIME字符串格式:
a.必须以vnd开头
b.若内容Uri以路径结尾,后接android.cursor.dir/,若内容Uri以id结尾,后接android.cursor.item/
c.最后接vnd…
当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver类来完成,要获取ContentResolver对象,可以使用Context提供的getContentResolver()方法。
ContentResolver cr = getContentResolver();
ContentResolver提供的方法和ContentProvider提供的方法对应的有以下几个方法。
public Uri insert(Uri uri, ContentValues values) 用于添加数据到指定Uri的ContentProvider中。
public int delete(Uri uri, String selection, String[] selectionArgs) 用于从指定Uri的ContentProvider中删除数据。
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 用于更新指定Uri的ContentProvider中的数据。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 用于查询指定Uri的ContentProvider。
Uri指定了将要操作的ContentProvider,其实可以把一个Uri看作是一个网址,我们把Uri分为三部分。
第一部分是"content://“。可以看作是网址中的"http://”。
第二部分是主机名或authority,用于唯一标识这个ContentProvider,外部应用需要根据这个标识来找到它。可以看作是网址中的主机名,比如"blog.csdn.net"。
第三部分是路径名,用来表示将要操作的数据。可以看作网址中细分的内容路径。
为了便于进行系统级别的消息通知,Android引入一套类似广播的消息机制,允许应用程序自由地发送和接收广播。
Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器)。广播作为Android组件间的通信方式,可以使用的场景如下:
1.同一app内部的同一组件内的消息通信(单个或多个线程之间);
2.同一app内部的不同组件之间的消息通信(单个进程);
3.同一app具有多个进程的不同组件之间的消息通信;
4.不同app之间的组件之间消息通信;
5.Android系统在特定情况下与App之间的消息通信。
(1)按照发送的方式分类
①标准广播
是一种异步的方式来进行传播的,广播发出去之后,所有的广播接收者几乎是同一时间收到消息的。他们之间没有先后顺序可言,而且这种广播是没法被截断的。
②有序广播
是一种同步执行的广播,在广播发出去之后,同一时刻只有一个广播接收器可以收到消息。当广播中的逻辑执行完成后,广播才会继续传播。
(2)按照注册的方式分类
①动态注册广播
所谓动态注册是指在代码中注册。步骤如下 :
在Activity中onResume()注册,onPause()销毁。
原因: 两个方法成对出现;
onPause()在Activity死亡之前一定会被执行,确保Broadcast在APP死亡之前一定会被注销。
不在onStop()和onDestroy()中销毁,是因为有时候onStop()和onDestroy()不会被执行。
②静态注册广播
动态注册要求程序必须在运行时才能进行,有一定的局限性,如果我们需要在程序还没启动的时候就可以接收到注册的广播,就需要静态注册了。主要是在AndroidManifest中进行注册。
两者及其接收广播的区别:
(1)动态注册广播不是常驻型广播,也就是说广播跟随Activity的生命周期。注意在Activity结束前,移除广播接收器。
静态注册是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。
(2)当广播为有序广播时:优先级高的先接收(不分静态和动态)。同优先级的广播接收器,动态优先于静态
(3)同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。
(4)当广播为默认广播时:无视优先级,动态广播接收器优先于静态广播接收器。同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后册的。
(3)按照定义的方式分类
①系统广播
Android系统中内置了多个系统广播,每个系统广播都具有特定的intent-filter,其中主要包括具体的action,系统广播发出后,将被相应的BroadcastReceiver接收。系统广播在系统内部当特定事件发生时,由系统自动发出。
系统广播,只要手机的基本操作发生变化(如开机、网络状态变化、拍照等等),都会发出相应的广播。当使用系统广播的时候,只需要在注册广播接收者时候定义相关的action即可,不需要我们手动的发送广播,系统会自动捕获。常见的如表格所示:
系统操作 | action |
---|---|
监听网络变化 | android.net.conn.CONNECTIVITY_CHANGE |
关闭或打开飞行模式 | Intent.ACTION_AIRPLANE_MODE_CHANGED |
充电时或电量发生变化 | Intent.ACTION_BATTERY_CHANGED |
电池电量低 | Intent.ACTION_BATTERY_LOW |
电池电量充足(即从电量低变化到饱满时会发出广播 | Intent.ACTION_BATTERY_OKAY |
系统启动完成后(仅广播一次) | Intent.ACTION_BOOT_COMPLETED |
按下照相时的拍照按键(硬件按键)时 | Intent.ACTION_CAMERA_BUTTON |
屏幕锁屏 | Intent.ACTION_CLOSE_SYSTEM_DIALOGS |
设备当前设置被改变时(界面语言、设备方向等) | Intent.ACTION_CONFIGURATION_CHANGED |
插入耳机时 | Intent.ACTION_HEADSET_PLUG |
未正确移除SD卡但已取出来时(正确移除方法:设置–SD卡和设备内存–卸载SD卡) | Intent.ACTION_MEDIA_BAD_REMOVAL |
插入外部储存装置(如SD卡) | Intent.ACTION_MEDIA_CHECKING |
成功安装APK | Intent.ACTION_PACKAGE_ADDED |
成功删除APK | Intent.ACTION_PACKAGE_REMOVED |
重启设备 | Intent.ACTION_REBOOT |
屏幕被关闭 | Intent.ACTION_SCREEN_OFF |
屏幕被打开 | Intent.ACTION_SCREEN_ON |
关闭系统时 | Intent.ACTION_SHUTDOWN |
②自定义广播
由应用程序开发者自己定义的广播
静态:常驻进程中,不受组件生命周期影响
动态:跟随组件的生命周期变化,如果Activity销毁,那么广播接收器也被销毁。
缺点:必须在程序启动后才能接收广播,因为注册的逻辑是写在onCreate()方法中的。
①静态:需要时刻监听广播。计算每隔一段时间的网络访问量:可静态注册,后台保存数据。
如—开机广播
②动态注册:需要在特定时刻接受广播。
如—监听手机是否插入耳机广播
动态+静态注册
如—监听手机屏幕解锁开锁
扩展:
隐式广播:指哪些没有具体指定发送给哪个应用程序的广播,大多数系统广播属于隐式广播,但少数特殊的广播仍使用静态注册的方式来接收。所有隐式广播不允许使用静态注册的方式来接收了。