Android基础知识

一、布局(四种)

1.LinearLayout(线性布局)

显示:所有子控件按照横向或者竖向依次排列,
属性:
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:控制该组件在父容器里的对齐方式。

2.RelativeLayout (相对布局)

显示:所有子控件默认显示在RelativeLayout的左上角
属性:

gravity:设置容器内组件的对齐方式
ignoreGravity:设置了属性为true属性的组件,将不受gravity属性的影响

3.GridLayout (网格布局)

显示:所有子控件默认在GridLayout中横向依次排列,当只等每行的列数时,到达指定列数会自动换行显示。
属性:

layout_column 在网格的第几列
layout_row 在网格的第几行
layout_columnSpan 跨列
layout_rowSpan 跨行
layout_gravity 在一个网格中的重心位置
columnCount 每行列总数

4.FrameLayout (帧布局)

显示:所有的子控件默认显示在FrameLayout的左上角,会重叠在一起显示。
属性:

foreground:用来设置帧布局容器的前景图像。
foregroundGravity:用来设置帧布局容器的前景图像显示的位置。

5.RelativeLayout.LayoutParams的使用

后期补

二、控件

1.TextView

作用: 文本展示
属性:

//控件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文件,定义控件展示效果

2.Button

作用: 按钮
属性:

//控件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属性

3.EditText

作用: 输入框,可编辑
属性:

//控件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()
光标位置的控制

4.ImageView

作用: 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属性

5.ProgressBar

作用: 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(不可见且不占据空间)

三、Activity

与用户进行交互

1.Activity使用

1)自定义Activity类名,继承Activity类或者其他子类
(2)重写onCreate()方法,在方法中调用setContentView()设置要显示的视图
(3)在AndroidMainfest.xml对Activity进行注册
(4)启动Activity:调用startActivity(intent);

2.Activity生命周期

**重点

1)onCreate():在活动第一次被创建的时候调用,用来完成活动的初始化操作,如加载布局、绑定事件等
(2)onStart():在活动由不可见变为可见时被调用
(3)onResume():在活动准备和用户交互的时候被调用。此时的活动一定位于返回栈的栈顶,并且处于运行状态
(4)onPause():在系统准备去启动或者恢复另外一个活动的时候调用。在此方法中将一些消耗CPU的资源释放,以及保存一些关键数据,,但这个方法一定要快,不然会影响到新的栈顶活动的使用
(5)onStop():在活动完全不可用时被调用。和onPause()的区别在于,如果启动一个对话框式的活动,那么onPause()方法会执行,而onStop()不会执行
(6)ondestroy():在活动被销毁之前调用,之后活动的状态将变为销毁态
(7)onRestart():在活动由停止状态变为运行状态之前调用,就是活动被重新启动

3.启动方式

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" />

4.启动模式

(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只能复用此实例。

5.横竖屏设置

拓展

http://t.csdn.cn/pnY4c

6.数据传递

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

1.fragment基本知识——碎片

特点:
①Fragment是依赖于Activity的,不能独立存在的。
②一个Activity里可以有多个Fragment,而一个Fragment可以被多个Activity重用。
③Fragment有自己的生命周期,并能接收输入事件。
④能在Activity运行时动态地添加或删除Fragment。

2、fragment的生命周期

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()

3、加载Fragment

(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();

4、Fragment与Activity的交互

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);

5、Fragment+ViewPager

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

adapter是view和数据的桥梁

1、BaseAdapter

(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

service是一种可以在后台执行长时间运行操作而没有用户界面的应用组件。服务可由其他应用组件启动(activity),服务一旦启动将在后台一直运行,即使启动服务的组件(activity)已销毁也不影响。此外组件可以绑定到服务,以与之进行交互,甚至是执行进程间通讯(IPC)。

1、Service的两种形式

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生命周期图,如下所示:
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也不会被销毁!

2、IntentService

  • 客户端通过startService(Intent)来启动IntentService; 我们并不需要手动地区控制IntentService,当任务执行完后,IntentService会自动停止; 可以启动IntentService多次,每个耗时操作会以工作队列的方式在IntentService的 onHandleIntent回调方法中执行,并且每次只会执行一个工作线程,执行完一,再到二这样!

3、前台服务

  • Service一般都是运行在后来的,但是Service的系统优先级 还是比较低的,当系统内存不足的时候,就有可能回收正在后台运行的Service,对于这种情况我们可以使用前台服务,从而让Service稍微没那么容易被系统杀死,当然还是有可能被杀死的…所谓的前台服务就是状态栏显示的Notification!

4、后台定时线程

  • 执行定时任务, 比如轮询,就是每间隔一段时间就请求一次服务器,确认客户端状态或者进行信息更新等!Android常用的定时方法是Alarm机制,它具有唤醒CPU的功能,也要区分CPU 唤醒与屏幕唤醒!

七、异常消息处理机制

1.Hander
2.AsyncTask
3.Binder机制
4.AIDL

八、数据储存

详见专栏Android中 数据库

九、ContentProvider

1、定义

   ContentProvider(内容提供者)是Android中的四大组件之一。主要用于对外共享数据,也就是通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider对指定应用中的数据进行操作。

2、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) 用于查询指定UriContentProvider,返回一个Cursor
public Uri insert(Uri, ContentValues) 用于添加数据到指定UriContentProviderpublic int update(Uri, ContentValues, String, String[]) 用于更新指定UriContentProvider中的数据
public int delete(Uri, String, String[]) 用于从指定UriContentProvider中删除数据
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…

3、ContentResolver

当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver类来完成,要获取ContentResolver对象,可以使用Context提供的getContentResolver()方法。

ContentResolver cr = getContentResolver();

ContentResolver提供的方法和ContentProvider提供的方法对应的有以下几个方法。

public Uri insert(Uri uri, ContentValues values) 用于添加数据到指定UriContentProvider中。
public int delete(Uri uri, String selection, String[] selectionArgs) 用于从指定UriContentProvider中删除数据。
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 用于更新指定UriContentProvider中的数据。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 用于查询指定UriContentProvider

4、Uri

   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、广播的分类

(1)按照发送的方式分类
①标准广播
是一种异步的方式来进行传播的,广播发出去之后,所有的广播接收者几乎是同一时间收到消息的。他们之间没有先后顺序可言,而且这种广播是没法被截断的。
②有序广播
是一种同步执行的广播,在广播发出去之后,同一时刻只有一个广播接收器可以收到消息。当广播中的逻辑执行完成后,广播才会继续传播。
(2)按照注册的方式分类
①动态注册广播
所谓动态注册是指在代码中注册。步骤如下 :

  1. 实例化自定义的广播接收器。
  2. 创建IntentFilter实例。
  3. 调用IntentFilter实例的addAction()方法添加监听的广播类型。
  4. 最后调用Context的registerReceiver(BroadcastReceiver,IntentFilter)动态的注册广播。

在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
成功安装APKIntent.ACTION_PACKAGE_ADDED
成功删除APKIntent.ACTION_PACKAGE_REMOVED
重启设备Intent.ACTION_REBOOT
屏幕被关闭Intent.ACTION_SCREEN_OFF
屏幕被打开Intent.ACTION_SCREEN_ON
关闭系统时Intent.ACTION_SHUTDOWN

②自定义广播
由应用程序开发者自己定义的广播

2、特点

静态:常驻进程中,不受组件生命周期影响
动态:跟随组件的生命周期变化,如果Activity销毁,那么广播接收器也被销毁。
缺点:必须在程序启动后才能接收广播,因为注册的逻辑是写在onCreate()方法中的。

3、应用

①静态:需要时刻监听广播。计算每隔一段时间的网络访问量:可静态注册,后台保存数据。
如—开机广播
②动态注册:需要在特定时刻接受广播。
如—监听手机是否插入耳机广播
动态+静态注册
如—监听手机屏幕解锁开锁

扩展:
隐式广播:指哪些没有具体指定发送给哪个应用程序的广播,大多数系统广播属于隐式广播,但少数特殊的广播仍使用静态注册的方式来接收。所有隐式广播不允许使用静态注册的方式来接收了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值