网络知识 娱乐 【安卓】安卓考试重点总结

【安卓】安卓考试重点总结

Android考试重点

Android虚拟设备的缩写:AVD

Android SDK目前支持的操作系统是:Linux

1.四大组件

activity(活动):Activity是Android中最基本的元素,负责与用户交互的组件, 代表可视的一屏,构造应用程序界面的组件,一个Activity中可以放置多个控件,如按钮等,也可以理解为控件的容器。

当我们创建完毕Activity之后,需要调用setContentView()方法来完成界面的显示;以此来为用户提供交互的入口。在Android App 中只要能看见的几乎都要依托于Activity,所以Activity是在开发中使用最频繁的一种组件。

service(服务):是不可见的后台运行的程序,可以为整个应用程序提供服务支持。是一个专门在后台处理长时间任务的Android组件,它没有UI。

a. 后台长期运行的服务(如音乐播放器,下载服务等) b. 进程间调用服务 c. 无需同用户进行交互(无UI)

它通常用作在后台处理耗时的逻辑,与Activity一样,它存在自己的生命周期,也需要在AndroidManifest.xml配置相关信息。它有两种启动方式,startService和bindService。

两种启动方式的区别(应该不会考):

startService只是启动Service,启动它的组件(如Activity)和Service并没有关联,只有当Service调用stopSelf或者其他组件调用stopService服务才会终止。
bindService方法启动Service,其他组件可以通过回调获取Service的代理对象和Service交互,而这两方也进行了绑定,当启动方销毁时,Service也会自动进行unBind操作,当发现所有绑定都进行了unBind时才会销毁Service。

broadcast(广播):是在组件之间传播 数据(Intent)的一种机制。

特性:

◼ 1.广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁
◼ 2.广播接收者中不要做一些耗时的工作,否则会弹出Application No Response错误对话框
◼ 3.最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉
◼ 4.耗时的较长的工作最好放在服务中完成

contentprovider(内容提供者):多个应用中存储和读取数据

◼ Android有一个独特之处就是,数据库只能被它的创建者所使用,其他的应用是不能访问到的,所以如果你想实现不同应用之间的数据共享,就不得不用Provider
◼ Android中的Content Provider机制可支持在多个应用中存储和读取数据。这也是跨应用共享数据的唯一方式。
◼ 提供了存储和获取数据提供了统一的接口
◼ 在不同的应用之间共享数据

Toast:

Toast是Android中用来显示显示信息的一种机制,和Dialog不一样的是,Toast是没有焦点的,而且Toast显示的时间有限,过一定的时间就会自动消失。下面用一个实例来看看如何使用Toast。

Toast.makeText(context, “安卓及格”, Toast.LENGTH_SHORT).show()

  1. 第一个参数:上下文
  2. 第二个参数:要显示的内容
  3. 第三个参数:Toast显示的时间(可以选择LENGTH_SHORT和LENGTH_LONG)
  4. .show()显示

img

自定义toast时间:

private void CustomTimeToast() {
         final Toast toast = Toast.makeText(this, "自定义Toast的时间",Toast.LENGTH_LONG);
         final Timer timer = new Timer();
         timer.schedule(new TimerTask() {
             @Override
             public void run() {
                 toast.show();
             }
         }, 0, 3000);// 3000表示点击按钮之后,Toast延迟3000ms后显示
         new Timer().schedule(new TimerTask() {
             @Override
             public void run() {
                 toast.cancel();
                 timer.cancel();
             }
         }, 5000);// 5000表示Toast显示时间为5秒
     }

selector:

selector是android中常用的状态选择器,一般都用来实现组件背景的状态变换。

selector可以设置颜色状态(color-selector)(颜色选择器样式一般放置在res/color文件夹下,一般用于背景或文字的选择样式)

和背景图状态(drawable-selector)(图片选择器样式一般放置在res/drawable文件夹下,一般用于背景选择样式)

常用的属性:

//设置是否按压状态,一般在true时设置该属性,表示已按压状态,默认为false
android:state_pressed
//设置是否选中状态,true表示已选中,false表示未选中
android:state_selected
//设置是否勾选状态,主要用于CheckBox和RadioButton,true表示已被勾选,false表示未被勾选
android:state_checked
//设置勾选是否可用状态,类似state_enabled,只是state_enabled会影响触摸或点击事件,state_checkable影响勾选事件
android:state_checkable
//设置是否获得焦点状态,true表示获得焦点,默认为false,表示未获得焦点
android:state_focused
//设置触摸或点击事件是否可用状态,一般只在false时设置该属性,表示不可用状态
android:state_enabled

颜色选择器:



       选中时候的颜色
    								没选中时的颜色
 

背景选择器:



     选中时候的颜色
    					  (上面的这串代表颜色)
    							 没选中时的颜色

fragment:

意为“碎片、片段”,可以将其看成小型的activity,也称为activity片段,将屏幕划分成几个片 段,再进行分组管理或模块化管理,更加方便地在运行过程中动态地更新activity的用户界面。

不能单独使用!!!需要嵌套在activity中

Fragment拥有自己的生命周期,但是还是会受到宿主Activity的生命周期的影响

Fragment的生命周期和Activity有点类似,有三种状态:

✓Resumed:在允许中的Fragment可见
✓Paused:所在Activity可见,但是得不到焦点
✓Stoped: 该Activity转向后台,或者该Fragment被替换/删除

FragmentTransaction常用方法:

✓ add(id, fragment) —— 增加framgent到队列中,并显示该fragment到指定布局中。

生命周期调用:
当fragment与activity连接并被建立时(onAttach()、onCreate()被调用过)
onCreateView()、onActivityCreated()、onStart()、onResume()。
当fragment与activity未连接并未被建立时(onAttach()、onCreate()未被调用过)
onAttach()、onCreate()、onCreateView()、onActivityCreated()、onStart()、onResume()。
注意:同一个Fragmen不能增加到队列两次或多次。

✓ remove(fragment) —— 销毁队列中指定的fragment。

生命周期调用:
当队列中不存在该fragment时,不会有任何反应。
当队列中存在该fragment时,fragment的生命周期执行情况主要依赖是否当前fragment进入到返回栈。

✓ replace(id, fragment) —— 先检查队列中是否已经存在,存在就会崩溃,不存在就会进入队列并把其他fragment清出队列,最后显示该fragment到指定布局中。

生命周期的调用:同add(id, fragment)。

✓ show(fragment) —— 显示队列中的指定framgent。

生命周期的调用:
当队列中不存在该fragment时,回调onAttach()、onCreate()。
当队列中存在该fragment时并被调用过hide(fragment)时,回调onHiddenChange(boolean)。
其他情况没有回调函数。

✓ hide(fragment) —— 隐藏队列中指定的fragment,相当于调用视图的.setVisibility(View.GONE)

生命周期的调用:
当队列中存在该fragment时,回调onHiddenChange(boolen)
当队列中不存在该fragment时,回调onAttach()、onCreate()、onHiddenChange(boolen)。

进行上述操作之后,要进行commit ,否则操作不会生效

image-20220610194834988

生命周期变化(方便理解,下面的可以不用刻意记,我感觉不会考。。应该):

Fragment被创建的时候:

onAttach()
onCreate()
onCreateView()
onActivityCreated()

Fragment对用户可见的时候,它会经历以下状态:

onStart()
onResume()

Fragment进入“后台模式”的时候

onPause()
onStop()

Fragment被销毁了(或者持有它的activity被销毁了):

onPause()
onStop()
onDestroyView()
onDestroy()
onDetach()

Fragment与Activity不同的生命周期:

Fragment的大部分状态都和Activity很相似,但fragment有一些新的状态。
Fragment不同于Activity的生命周期
onAttached() —— 当fragment被加入到activity时调用(在这个方法中可以获得所在的activity)。
onCreateView() —— 当activity要得到fragment的layout时,调用此方法,fragment在其中创建自己的layout(界面)。
onActivityCreated() —— 当activity的onCreated()方法返回后调用此方法
onDestroyView() —— 当fragment中的视图被移除的时候,调用这个方法。
onDetach() —— 当fragment和activity分离的时候,调用这个方法。
一旦activity进入resumed状态(也就是running状态),你就可以自由地添加和删除fragment了。因此,只有当activity在resumed状态时,fragment的生命周期才能独立的运转,其它时候是依赖于activity的生命周期变化的。

在这里插入图片描述

没理解的同学可以看一下这篇博客:

https://blog.csdn.net/lan266548_ning/article/details/80584502?ops_request_misc=&request_id=&biz_id=102&utm_term=fragment&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-80584502.142v13pc_search_result_control_group,157v14new_3&spm=1018.2226.3001.4187

handler:

Handler是一套Android消息传递机制,主要用于进程间通信,postDelayed方法可以实现延时自动启动。

用最简单的话描述: handler其实就是主线程在起了一个子线程,子线程运行并生成Message,Looper获取message并传递给Handler,Handler逐个获取子线程中的Message.

使用Handler消息传递机制主要是为了多个线程并发更新UI的同时,保证线程安全

Handler 对象:消息的真正处理者, 具备获取消息、发送 消息、处理消息、移除消息等功能

img

Android消息机制:

  • 以Handler的sendMessage方法为例,当发送一个消息后,会将此消息加入消息队列MessageQueue中。
  • Looper负责去遍历消息队列并且将队列中的消息分发给对应的Handler进行处理。
  • 在Handler的handleMessage方法中处理该消息,这就完成了一个消息的发送和处理过程。

SharedPreferences:

​ 属于移动存储解决方案
​ 键值对存储
​ 存放的数据类型不支持double。
​ 数据的保存格式是XML
​ 读取XML文件的路径是/data/data//shared_prefs下
​ 向SharedPreferences写入数据时,需要先获得的对象是Editor

SharedPreferences 类提供了一个通用框架,以便您能够保存和检索原始数据类型的永久性键值对。您可以使用 SharedPreferences 来保存任何原始数据:布尔值,浮点值,整型值,长整型和字符串。此数据将跨多个用户会话永久保留(即使您的应用已终止亦如此)。

SharedPreferences 使用 xml 格式为 Android 应用提供一种永久数据存贮方式,并且使用键值对的方式来存储数据的。相对于一个 Android 应用而言,目录 / data/data/your_app_package_name/shared_prefs / 下,可以被处在同一个应用中的所有 Activity 访问。Android 提供了相关的 API 来处理这些数据而不需要程序员直接操作这些文件或者考虑数据同步的问题。

SharedPreferences 本身是一个接口,程序无法直接创建 SharedPreferences 的实例,只能通过 Context 提供的 getSharedPreferences(String name,int mode) 方法来获取 SharedPreferences 的实例

getSharedPreferences(第一个参数,第二个参数)

​ 第一个参数是存储时的名称,用于指定 SharedPreferences 文件的名称(格式为 xml 文件),如果该名称的文件不存在则会创建一个
​ 第二个参数则是文件的打开方式
​ 打开方式:
​ MODE_PRIVATE,则该配置文件只能被自己的应用程序访问
​ MODE_WORLD_READABLE,则该配置文件除了自己访问外还可以被其它应该程序读取
​ MODE_WORLD_WRITEABLE,则该配置文件除了自己访问外还可以被其它应该程序读取和写入

此外还得提一下 SharedPreferences.Editor 对象的一些主要方法

  • SharedPreferences.Editor clear(): 删 SharedPreferences 中所有的数据。
  • SharedPreferences.Editor putXxx(String key , xxx value): 向 SharedPreferences 存入指定 key 对应的数据,其中 xxx 可以是 booleant 等各种基本类型数据 。
  • SharedPreferences.Editor remove(): 删除 SharedPreferences 中指定 key 对应的数据项
  • boolean commit(): Editor 编辑完成后,使用该方法同步提交修改。
  • void apply(): Editor 编辑完成后,使用该方法异步提交修改。

将数据保存至SharedPreferences代码操作:

SharedPreferences preferences=getSharedPreferences("user",Context.MODE_PRIVATE);
Editor editor=preferences.edit();
String name="xixi";
String age="22";
editor.putString("name", name);
editor.putString("age", age);
editor.commit();

从SharedPreferences获取数据:

SharedPreferences preferences=getSharedPreferences("user", Context.MODE_PRIVATE);
String name=preferences.getString("name", "defaultname");
String age=preferences.getString("age", "0");

内容提供器ContentProvider:

作用是实现数据共享和交换,是Android实现跨程序数据共享的标准方式。

搭配ContentResolver使用,增删查改方法都在ContentResolver对象中,可以在Activity中得到ContentResolver实例对象的方法是getContentrResolver()

前面四大组件有提到基本概念,进程间共享数据的本质是:添加、删除、获取 & 修改(更新)数据

所以ContentProvider的核心方法也主要是上述4个作用

ContentResolver 类提供了与ContentProvider类相同名字 & 作用的4个方法

// 外部进程向 ContentProvider 中添加数据
public Uri insert(Uri uri, ContentValues values)  

// 外部进程 删除 ContentProvider 中的数据
public int delete(Uri uri, String selection, String[] selectionArgs)

// 外部进程更新 ContentProvider 中的数据
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)  

// 外部应用 获取 ContentProvider 中的数据
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

实例:

// 使用ContentResolver前,需要先获取ContentResolver
// 可通过在所有继承Context的类中 通过调用getContentResolver()来获得ContentResolver
ContentResolver resolver =  getContentResolver(); 

// 设置ContentProvider的URI
Uri uri = Uri.parse("content://cn.scu.myprovider/user"); 
 
// 根据URI 操作 ContentProvider中的数据
// 此处是获取ContentProvider中 user表的所有记录 
Cursor cursor = resolver.query(uri, null, null, null, "userid desc"); 

信使intent:

intent.putExtra和getXXXExtra的使用

intent启动组件:startActivity、startService、startActivityForResult

可以实现界面间的切换,可以包含动作和动作数据,连接四大组件的纽带

Extra属性

通过使用Intent对象的putExtra()方法来添加附加信息、和信息传递
信息添加 方式类似于键值对

Intent intent= new Intent();
intent.putExtra("name","zhangsan");

信息取出 另一个页面
通过使用Intent对象的getXXXExtra()方法可以获取附加信息。
例如,将上面代码存入Intent对象中的人名获取出来,
因存入的是字符串,所以可以使用getStringExtra()方法获取数据

 Intent intent = getIntent();
 String name=intent.getStringExtra("name");

跳转页面代码演示:

public void exam_button(View view) {  //控件点击事件
        //创建Intent对象,传入两个参数,第一个是上下文,第二个是目标活动
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        startActivity(intent);//启动方法,跳转页面
    }

跳转指定网页代码演示:

public void baidu(View view) {  //控件点击事件
        Intent intent = new Intent(Intent.ACTION_VIEW);  //调用系统内置动作
        //用Uri.parse()方法将网址字符串解析成uri对象,再用Intent的setData()方法将Uri对象传递进去
        intent.setData(Uri.parse("http://www.baidu.com"));
        startActivity(intent);//启动页面
    }

传递数据代码演示:

public void transmission_value() {
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);.
        //putExtra()方法重载,传入的数据暂时存在Intent中,启动页面后再从Intent取出就可以了
        intent.putExtra("extra_data", "my_data");//第一个是键值,用于后面Intent取值,第二个是传递的数据
        startActivity(intent);
    }
    
//getIntent()方法获取启动SecondActivity的Intent,
Intent intent = getIntent();
//然后调用getStringExtra()方法,传入相应的键值,就可以得到传递的数据
String my_data = intent.getStringExtra("extra_data");  //获取Intent传account的index

详细解释可以看一下这篇博客:Android页面跳转(Intent)_青素i的博客-CSDN博客_android intent跳转页面

activity生命周期方法:

(1)onCreate:表示Activity正在被创建,这是生命周期的第一个方法。可以在该方法中做一些初始化工作, 
(2)onStart:表示Activity正在被启动,即将开始,这是Activity已经可见了,但是还没有出现在前台,还无法和用户进行交互。
(3)onRestart:表示Activity正在重新启动。一般情况下,当当前Activity从不可见重新变为可见状态时,onRestart就会被调用。
(4)onResume:表示Activity已经可见了,并且出现在前台并开始活动。要注意这个和onStart的对比,onStart和onResume都表示Activity已经可见,但是onStart的时候Activity还在后台,onResume的时候Activity才显示到前台。
(5)onPause:表示Activity正在停止,正常情况下,紧接着onStop就会被调用。在特殊情况下,如果这个时候快速地再回到当前Activity,那么onResume会被调用。这种情况属于极端情况,用户操作很难重现这一场景。此时可以做一些存储数据、停止动画等工作,但是注意不能太耗时,因为这会影响到新Activity的显示,onPause必须先执行完,新Activity的onResume才会执行。
(6)onStop:表示Activity即将停止,可以做一些稍微重量级的回收工作,同样不能太耗时。
(7)onDestroy:表示Activity即将被销毁,这是Activity生命周期中的最后一个回调。可以在该方法中做一些回收工作和最终的资源释放。

android七大布局:

(1)线性布局:LinearLayout
		该布局可以使放入其中的组件以水平方式或者垂直方式整齐排列,通过 android:orientation 属性指定具体的排列方式,通过 weight 属性设置每个组件在布局中所占的比重。
(2)相对布局:RelativeLayout
		这种布局方式是以一种让组件以相对于容器或者相对于容器中的另一个组件的相对位置进行放置的布局方式
(3)表格布局:TableLayout
		以行列的方式管理组件
(4)层(帧)布局:FrameLayout
		它指定屏幕上的一块空白区域,在该区域填充一个单一对象
(5)绝对布局:AbsoluteLayout
		放入该布局的组件需要通过 android:layout_x 和 android:layout_y 两个属性指定其准确的坐标值,并显示在屏幕上
(6)网格布局:GridLayout
		网格布局相对于表格布局来说自由度更高,是以行数和列数来确定位置进行排列
(7)约束布局:ConstraintLayout
		可以按照比例约束控件位置和尺寸,更好适配屏幕大小的不同机型。

事件模型:

事件、事件源、事件监听器

Android为view提供的5种事件处理的回调方法:
onKeyDown() 该方法用来捕捉手机键盘被按下的事件
onKeyUp() 该方法用来捕捉手机键盘按键抬起的事件
onTouchEvent() 该方法处理手机屏幕的触摸事件
onTrackBallEvent() 该方法是手机中轨迹球的处理方法
onFocusChanged() 该方法是焦点改变的回调方法

Android的事件处理机制:

基于监听的事件处理
基于回调的事件处理

监听:
为Android的组件绑定特定的事件监听器,当触发相应的事件时,会调用这些方法;

三个对象:
1.事件源也就是事件发生的场所,通常为各个组件
2.事件
3.事件监听器

事件监听的四种方法:

1.创建一个外部类,实现接口
    public class ClickOkListener implements OnClickListener
    {
        //重写OnClick方法
    }
    //**************************************//
    //在Activity中调用
    btn.setOnClickListener(new ClickOkListener)
2.匿名内部类的方式
    btn.setOnClickListener(new OnClickListener(){
        onClick()
        {
            //处理事件
        }
    });
3.Activity作为事件监听器
    (1).btn.setOnCLickListener(this)
    (2).让Activity implements OnCLickListener
    (3).在Activity中重写onClick方法
4.通过在xml中设置onClick属性来绑定点击事件的处理
    

事件处理的先后顺序:
1.监听
2.回调
3.当前的Activity

notification代码(发送通知)

public class NotificationActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_notification);
    }
}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".shopcar.fragment.NotificationActivity">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="通知跳转成功"/>
</LinearLayout>

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Intent intent = new Intent(this, NotificationActivity.class);
//        要跳转的页面
        PendingIntent activity = PendingIntent.getActivity(this, 0, intent, 0);
//        通知管理器
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Notification notification = new NotificationCompat
                .Builder(this, "一般通知")
                .setContentTitle("眼霜")
                .setContentText("原价1300,预售8.8折")
                .setTicker("29号活动截止")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.drawable.good1)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.mall_logo))
                .setContentIntent(activity)
                .setAutoCancel(true)
                .build();
        startForeground(4,notification);
    }

    @Override
    public IBinder onBind(Intent intent) {

        throw new UnsupportedOperationException("Not yet implemented");
    }
}

public class ShopCarFragment extends Fragment {

    @BindView(R.id.tv_shopcart_edit)
    TextView tvShopcartEdit;
    @BindView(R.id.shopcar_recycle)
    RecyclerView shopcarRecycle;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_shop_car, container, false);
//        1、绑定butterknife
        ButterKnife.bind(this, view);

//        初始化数据
        initShopcarData();
//
//        new Handler().postDelayed(new Runnable() {
//            @Override
//            public void run() {
                跳转通知
                popNotification();
                样式通知
                popTableNotification();
                popServiceNotification();
//            }
//        }, 2000);

        tvShopcartEdit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//                退出登录
                SharedPreferences.Editor editor = getActivity().getSharedPreferences("data", MODE_PRIVATE).edit();
                editor.remove("username");
                editor.remove("password");
                editor.commit();
            }
        });

        return view;
    }

    private void initShopcarData() {

    }

//    //    后台通知
    private void popServiceNotification() {
        getActivity().startService(new Intent(getContext(), MyService.class));
    }
//
//    //    大文本通知
    private void popTableNotification() {
//        1、多行显示通知
        NotificationCompat.InboxStyle style = new NotificationCompat
                .InboxStyle()
                .setBigContentTitle("SK2神仙水第一次打折啦")
                .setSummaryText("折扣详情")
                .addLine("神仙爽肤水 230ml 原价1540 今日20点秒杀999")
                .addLine("小灯泡 30ml 原价1260 今日20点秒杀888");

       /2、大文本通知
        NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle().bigText("SK2神仙水第一次打折啦SK2神仙水第一次打折啦SK2神仙水第一次打折啦SK2神仙水第一次打折啦SK2神仙水第一次打折啦SK2神仙水第一次打折啦");

        3、大图
        NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(), R.drawable.image_2));

        NotificationManager manager = (NotificationManager) getActivity().getSystemService(NOTIFICATION_SERVICE);
        Notification notification = new NotificationCompat
                .Builder(getContext(), "样式通知")
                .setSmallIcon(R.drawable.a)
//                .setStyle(style)
                .setDefaults(Notification.DEFAULT_ALL)
//                .setVibrate(new long[]{0,5000,5000,7000})
//                .setDefaults(Notification.DEFAULT_SOUND)
                .setAutoCancel(true)
                .setPriority(Notification.PRIORITY_HIGH)
                .build();
        manager.notify(3, notification);
    }

    //    弹出通知--跳转页面
    private void popNotification() {
        Intent intent = new Intent(getContext(), NotificationActivity.class);
//        要跳转的页面
        PendingIntent activity = PendingIntent.getActivity(getContext(), 0, intent, 0);
//        通知管理器
        NotificationManager manager = (NotificationManager) getActivity().getSystemService(NOTIFICATION_SERVICE);
        Notification notification = new NotificationCompat
                .Builder(getContext(), "一般通知")
                .setContentTitle("雅诗兰黛黑钻眼霜")
                .setContentText("原价1300,预售8.8折")
                .setTicker("29号活动截止")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.drawable.good1)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.mall_logo))
                .setContentIntent(activity)
                .setAutoCancel(true)
                .build();
//        发送通知
        manager.notify(1, notification);
    }

}1)获取NotificationManager通知管理器
(2)构建Notification对象:
使用Notification.Builder构建器构建对象.
Builder builder = new Builder();
builder.setXXX().setXXX().build();3)调用manager.notify()方法发送该通知。
例子:
private static final int NOTIFICATION_ID = 1001;
private void sendNotification() {
        //1、NotificationManager
        NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
        /** 2、Builder->Notification
         *  必要属性有三项
         *  小图标,通过 setSmallIcon() 方法设置
         *  标题,通过 setContentTitle() 方法设置
         *  内容,通过 setContentText() 方法设置
         * */
        Notification.Builder builder = new Notification.Builder(this);
        builder.setContentInfo("Content info")
                .setContentText("Content text")//设置通知内容
                .setContentTitle("Content title")//设置通知标题
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher))
                .setSmallIcon(R.mipmap.ic_launcher_round)//不能缺少的一个属性
                .setSubText("Subtext")
                .setTicker("滚动消息......"