Android基础

Android系统介绍:

    Android系统由安迪鲁宾团队开发,初衷是要在智能相机上发展,05年8月被谷歌收购,发展移动端.

Android应用范围:

    手机,平板,智能家居,可穿戴设备

Android系统架构:

    application(应用层-java):运行我们平常安装的Android程序APP

    application fromework(应用框架层-java/JNI):在遵循框架的安全性限制范围内,任何应用程序都可以发布自己的功能块并且任何应用程序都可以使用其所发布的功能块(为上层应用程序提供了一些类,函数.可以调用)

    libraries+dalvik(函数库+虚拟机-C/C++):提供了一些函数,包括C/C++函数

    linux kernel(内核驱动层-C):liunx系统代码

    JNI:Java Native Interface在c/c++ java之间的相互调用

JVM和DVM的区别?

  1. 版权不同:JVM---sun公司        DVM----google公司

  2. 所给基于的架构不同:

    1. JVM基于栈,栈位于内存上的一个空间,每执行一个指令都要想CPU寻址

    2. DVM基于寄存器,是CPU的一个组成部分,处理指令操作无需寻址,直接执行

  3. 执行的文件类型不通过:

    1. JVM执行的是多个.class文件

    2. DVM执行的是一个.dex文件

ART模式:Android runtime

    采用的是空间换时间的概念;由于安装的时候需要进行预编译,所以安装的时间比较长,预编译会产生大量的机器码,所以会占用一定的存储空间,预编译产生的机器码在程序运行的时候无需实时的进行转化,所以运行速度相对比较快

Android开发工具:

    JDK:开发环境    Eclipse(旧时代):开发工具    AndroidStudio(新时代):开发工具

    网址链接:http://www.androiddevtools.cn/

ADB指令:

    adb:Android Debug Bridge建立手机端和PC端之间的连接

    adb debices:列出当前电脑锁所连接的Android设备

Intent(意图):

//创建意图对象
Intent intent = new Intent();
//为意图对象设置动作
intent.setAction()
//启动意图
startActivity(intent);
//在清单文件中设置拨打电话的权限
//<uses-permission android:name="android.permission.CALL_PHONE"/>

按钮的四种点击方式:

  1. 匿名内部类的方法

  2. 让当前类实现OnClickListener接口

  3. 创建一个类实现OnClickListener接口:按钮比较多的时候用着方便

  4. 为控件添加onClick属性,在该空间对应的Activity中添加以这个属性值命名的方法

Android常用的布局:

  1. LinearLayout(线性布局):要么横向从左向右排列;要么纵向从上到下排列

  2. RealtiveLayout(相对布局):给控件一个参照物,设定对应这个参照物的上下左右位置或者距离

  3. FrameLayout(帧布局):一层一层的向上叠加

  4. TableLayout(表格布局):布局中的一个TableRow代表一行,TableRow中的一个控件代表一列

  5. AbsoluteLayout(绝对布局):以坐标的方式来定位控件在屏幕上的位置,没有绝对定位的情况下相比其它类型的布局更加难以维护,灵活性差

测试:

    根据是否知道源码:    黑盒测试    白盒测试

    根据测试的粒度:    方法测试    单元测试    集成测试    系统测试

    根据测试的暴力程度:    冒烟测试    压力测试

  1. 单元测试:写一个类继承AndroidTestCase,这个类就具备了单元测试的功能,可以在此类中测试我们要测试的方法

  2. 在清单文件manifest节点下配置

    1. <instrumentation
              android:name="android.test.InstrumentationTestRunner"
              android:targetPackage="com.itheima.junit" />
  3. 在application节点下配置

    1. <uses-library android:name="android.test.runner" /> 
  4. 或者直接新建一个Android测试工程,配置文件中会自动生成相关配置

数据的存储:

  1. SharedPreferences存储:适用于保存少量数据,并且这些数据格式都非常简单

  2. 文件存储:通过IO流将数据写到指定文件名的文件上

  3. SQLite数据库存储:SQLite是轻量级嵌入式数据库,支持sql语言并且可以使用少量的内存就能发挥良好的性能,移动开发时使用它存储大量数据

  4. ContentProvider存储

  5. 网络存储

数据的解析:

    dom解析:基于全文加载解析,就是讲文件直接完全的一次性解析出来,比较消耗资源

    sax解析:基于事件的逐行解析,一行一行的解析

    pull解析:同sax解析原理形同

    sax和pull的区别

        sax:一行一行的逐行解析,中间不能中断,能修改内容

        pull:一行一行的逐行解析,中途可以中断,可以修改内容

    XML文件的生成两种方式:

        1.通过拼装生成XML文件

public static boolean backupSms(Context context, ArrayList<SmsBean> lists){
        
        StringBuilder sb = new StringBuilder();
        
        //拼装一个xml声明头信息
        sb.append("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>");
        //拼装一个xml根节点
        sb.append("<Smss>");
        
        //循环遍历结合中的短信数据
        for(SmsBean sms : lists){
            sb.append("<Sms id='" +sms.id + "'>");
            
            sb.append("num");
            sb.append(sms.num);
            sb.append("num");
            
            sb.append("msg");
            sb.append(sms.msg);
            sb.append("msg");
            
            sb.append("date");
            sb.append(sms.date);
            sb.append("date");
            
            sb.append("</Sms>");
        }
        sb.append("</Smss>");
        try {
            FileOutputStream openFileOutput = context.openFileOutput("backupsms.xml", Context.MODE_PRIVATE);
            openFileOutput.write(sb.toString().getBytes());
            openFileOutput.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

        2.通过序列化生成XML

public static boolean backupSmsFroAndroid(Context context, ArrayList<SmsBean> lists){
        try {
            //创建XmlSerializer对象
            XmlSerializer xs = Xml.newSerializer();
            //为XmlSerializer对象初始化文件写入流信息
            xs.setOutput(context.openFileOutput("backupsms.xml", Context.MODE_PRIVATE), "utf-8");
            //序列化xml声明头信息
            xs.startDocument("utf-8", true);
            //序列化XML的节点
            xs.startTag(null, "Smss");
            
            //循环便利根节点
            for(SmsBean smsBean : lists){
                xs.startTag(null, "Sms");
                xs.attribute(null, "id", smsBean.id);
                
                xs.startTag(null, "num");
                xs.text(smsBean.num);
                xs.endTag(null, "num");
                
                xs.startTag(null, "msg");
                xs.text(smsBean.msg);
                xs.endTag(null, "msg");
                
                xs.startTag(null, "date");
                xs.text(smsBean.date);
                xs.endTag(null, "date");
                
                xs.endTag(null, "Sms");
            }
            
            xs.endTag(null, "Smss");
            xs.endDocument();
            
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    pull解析XML文件:

//XML数据的解析
    public static int resoveSms(Context context){
        try {
            ArrayList<SmsBean> lists = null;
            SmsBean bean = null;
            //1.创建XmlPullParser对象
            XmlPullParser xpp = Xml.newPullParser();
            //2.为XmlPullParser对象初始化文件读取流
            Resources resources = context.getResources();//通过Context对象获取一个资源对象
            AssetManager assets = resources.getAssets();//通过资源对象获取一个Assets管理者
            InputStream open = assets.open("backupsms.xml");//通过Assets管理者获取一个文件的读取流
            xpp.setInput(open, "utf-8");
            //3.获取XmlPullParser对象的当前事件
            int type = xpp.getEventType();
            //4.判断当前事件类型是否是文档结束类型
            while(type != XmlPullParser.END_DOCUMENT){
                //5.如果不是文档结束就开始一行一行的解析数据,解析一行之后要获取下一行的事件类型
                //获取当前事件类型的名称
                String name = xpp.getName();
                //判断事件类型
                switch(type){
                case XmlPullParser.START_TAG:
                    if("Smss".equals(name)){
                        lists = new ArrayList<SmsBean>();
                    }else if("Sms".equals(name)){
                        bean =  new SmsBean();
                        bean.id = xpp.getAttributeValue(null, "id");
                    }else if("num".equals(name)){
                        bean.num = xpp.nextText();
                    }else if("msg".equals(name)){
                        bean.msg = xpp.nextText();
                    }else if("date".equals(name)){
                        bean.date = xpp.nextText();
                    }
                    break;
                case XmlPullParser.END_TAG:
                    if("Sms".equals(name)){
                        lists.add(bean);
                    }
                    break;
                }
                //获取下一行的事件类型
                type = xpp.next();
            }
            return lists.size();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

Android下数据库的创建:

    当有大量相同结构的数据需要存储时候,用数据库查询非常快

    数据库的创建:

        1.写一个类继承SqliteOpenHelper

        2.构造方法初始化数据库的名称

        3.实现抽象方法onCreate和onUpgrade方法

            a.onCreate:数据库第一次创建的时候调用,适合做表结构的初始化

            b.onUpgrade:数据库版本升级的时候调用,适合表结构的修改

        4.创建数据库帮助类对象,并调用getReadableDatabase或者getWritableDatabase

            getReadableDataase:首先以读写的方式打开数据库,如果磁盘满了,在尝试以只读的方式打开数据库

            getWritableDatabase:以只读的方式打开数据库,如果磁盘空间满了,抛出异常

    数据库实现增删改查两种方式:

        第一种方式:

            1.调用getReadableDatabase方法获取一个SqliteDatabase数据库帮助类对象

            2.使用SqliteDAtabase帮助类对象执行execSQL方法做增删改查;查询需要使用rawQuery方法,返回一个Cursor结果集对象,再遍历解析Cursor中的内容

        第二种方式:

            1.使用SqliteDatabase提供的insert delete update query方法实现增删改查方法

        两种方式的区别:

            第一种方式:增删改查没有返回值,无法判断sql语句是否执行成功,由于要手动写Sql语句容易写错

            第二种方式:增删改查有了返回值,可以知道执行的命令是否成功,查询不够灵活

数据库的事务:

    事务是访问数据库的一个操作序列,数据库应用系统通过事务集来完成对数据库的存取.事务的正确执行是的数据库从一种状态转换到另一个状态

    事务的作用:防止在对数据库进行复杂或者重要操作时中途突然出现异常,导致出错.出错驶入会回滚到进行操作之前的状态

ListView:

    android中一个控件,在一个垂直滚动列表中显示Item数据的控件,这些Item来自于ListAdapter的数据适配器.

    适配器:即写一个类继承BaseAdapter,实现四个方法;其中getCount()返回的是ListView要显示的条目数;getView()返回的是ListView条目要显示的内容,每当屏幕显示一个条目时就会调用一次getView方法.

    ListView的优化:getView方法会传进来一个converView对象,该对象是曾经使用过的View对象,我们可以重用该对象作为getView的返回对象,在使用之前先判断converView是否为空.

Handler消息机制:

    Handler消息的创建:每一个消息都要被指定的Handler处理,通过Handler创建消息便可完成.Android消息机制中引入了消息池.Handler创建消息时首先查询消息池中是否有消息存在,如果有直接从消息池中取出来,如果没有则重新初始化一个消息实例;消息池的好处:消息不被使用时,并不作为垃圾回收,而是放入消息池中,以供下次Handler创建消息时使用.提高了消息对象的复用,减少了系统回收垃圾的次数.

    Handler发送消息:主线程初始化第一个Handler时会通过ThreadLcoal创建一个Lopper,该Lopper与主线程一一对应.使用ThreadLcoal的目的是为了保证每一个线程只创建一个Looper.之后其他Handler初始化的时候直接获取第一个Handler创建的Looper.Looper初始化的时候会创建一个消息队列MessageQueue;Handler持有对主线程消息队列MessageQueue和消息循环Looper的引用,子线程可以通过Handler将消息发送到主线程的消息队列MessageQueue中

    Handler消息处理:主线程通过Looper循环查询消息队列,当发现有消息存在时将消息从消息队列中取出.分析消息,通过消息对应的Handler,将消息分发到指定的Handler进行处理

常见的消息处理:

    1.runOnUIThread(Runnable runnable):无论当前线程是否在主线程,执行的内容都会在主线程执行

    2.new Handler().postDelayed(Runnable, long);

      new Handler().postDelayed(new Runnable(){

        public void run(){

            Intent intent = new Intent(mContext, MainActivity.class);

            startActivity(intent);

        }

      },5000);

    3.使用Timer实现

      //创建一个定时器

      Timer timer = new Timer();

      //为定时器设置任务及时间

      timer.schedule(new TimerTask(){

            public void run() {

            //通过intent跳转到其他的Acitivty

            Intent intent = new Intent(mContext,MainActivity.class);

            startActivity(intent);

            }

       }, 5000);

网络请求get/post请求区别:

    1.请求的地址不同

    2.请求的参数不同

        相对于get请求,post中多了几个请求头和一个请求内容

    3.携带的数据大小不同

        get:1k    post:理论上暂时没有上限

Android四大组件:

    Activity(活动), BroadcastReceiver(广播接收者), Service(服务), ContentProvider(内容提供者)

    Android四大组件都要在清单文件中做配置,只要使用都要做配置

    Android四大组件都是运行在主线程中

Intent(意图):隐式意图和显示意图

    意图可以传递对象 字符串 八大基本数据类型

    显示意图:通过指定的包名或者类名,是显示意图.

        显示意图相对于隐式意图比较安全,用于开启自己应用的页面

    隐式意图:通过指定的动作,是隐式意图

        隐式意图用于开启其他应用的界面(其他应用多数指的是,系统自带的应用)

Activity(活动):

    Activity生命周期:

        onCreate():当Activity第一次启动的时候调用

        onStart():当Activity可见的时候调用

        onResume():当Activity获取焦点的时候(当界面上有按钮,并且可以被点击)

        onPause():当Activity是去焦点的时候(当界面上有按钮但不可以被点击时)

        onStop():当Activity不可见的时候调用

        onDeatory():当Activity销毁的时候调用

    横竖屏切换Activity的生命周期:

        onPause()→onStop()→onDestory()→onCreate()→onStart()→onResume()

    当进行横竖屏切换时Activity先销毁再开启,所以要对Activity进行横竖屏指定:

        1.android=screenOrientation="portrait"

        2.android:configChanges="keyboardHidden|orientation|screenSize"

        第二句的意思是让系统不再敏感横竖屏的变化

    任务栈:

        栈:先进后出

        队列:先进先出

        打开一个Activity相当于进栈,关闭一个Activity相当于出栈

        任务栈是用来维护Activity的,用户操作的永远是栈顶的Activity,当应用程序退出来就是任务栈被清空了.

    Activity四种启动模式:

        standard(系统默认的启动模式):

        singleTop(单一顶部模式):如果任务栈的栈顶存在准备开启的Activity,不会重复创建Activity,而是复用已经存在的Activity.保证栈顶如果存在,不会重复创建(浏览器书签)

        singleTask(单一任务栈):当开启Activity的时候,就去检查在任务栈里是否有实例存在,如果有实例存在就重用这个已经存在的Activity,并把这个Activity上面所有其他的Activity清空,保证整个任务栈中只有一个实例存在(浏览器)

        singleInstance(特殊的启动模式):Activity会运行在自己的任务栈中,并且这个任务栈中只有一个实例存在,如果要保证一个Activity在整个手机操作系统中只有一个实例存在,就是用singleInstance(来电页面)

BroadcastReceiver(广播接收者):

    有序广播和无序广播:

        无序广播:类似新闻联播;数据不可以修改,广播不可以被终止.

        有序广播:类似文件,一级一级的接收;数据可以被修改,广播可以被终止

    特殊的广播接收者:

        类似于特别频繁的广播事件(电量变化,锁屏,解锁)

        特殊广播接收者清单文件注册无效,需要进行代码注册;代码注册需要用到IntentFilter(意图过滤器)对象,通过addAction()方法添加指定的动作,registerReceiver()方法注册广播接收者.

    Style(样式)和Theme(主题):

        相同点:定义的方式是一样的

        不同点:作用的范围不同;Style作用范围比较窄,一般作用在控件上;Theme一般作用在控件上

    i18n(国际化):

        软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相对应的符合来访者阅读习惯的页面或者数据,简单说就是在res下创建相对应国家环境级目录

    常见对话框:

        AlertDialog, progressdialog, 普通对话框, 单选对话框, 多选对话框, 进度条对话框

Service(服务):

    服务是在后台运行,可以理解成是在后台运行但是没有界面的Activity

    this和getApplicationContext的区别?

        getApplicationContext返回的对象是Context,可以理解成父类

        this:代表的是当前Activity理解成子类

    进程:

        进程是正在运行的程序实体,它包括这个运行的程序中占据的所有的系统资源.同一个进程,在同一时刻被两次运行起来,那么他就是两个独立的进程.

    进程的状态:

        Freground Process(前台进程):用户正在交互 相当于Activity执行了onResume

        Visible Process(可视进程):用户还可以看得见 相当于Activity执行了onPause

        Service Process(服务进程):通过startService方式开启一个服务 播放音乐下载数据

        Background Process(后台进程):用户看不见页面 相当于Activity执行了onStop

        Empty Process(空进程):等待垃圾回收机制回收

    start方式开启服务的特点:

        1.第一次开启服务执行onCreate和onStart方法

        2.第二次开启服务只执行onStart方法

        3.服务一旦开启通过start方式开启,服务就会在后台一直长期运行,直到用户手动停止或者我们调用stopService关闭服务

    bind方式开启服务的特点:

        1.第一次开启服务执行onCreate和onBind方法

        2.当Activity销毁的时候,服务也会跟着销毁

        3.服务只能被解绑一次,多次解绑会报异常

        4.bind方式开启服务,服务在在设置页面看不到,相当于一个隐形的服务

        bindService作用:可以调用服务里面的方法

    进程间通信:(AIDL)

        AIDL(Android Interface Definition Language/Android接口定义语言)

        远程服务:运行在其他应用程序里面的服务

        本地服务:运行在自己应用里面的服务

        AIDL使用大致步骤:

            1.将Iservice.Java文件变成aidl结尾的文件

            2.将文件中的public去掉

            3.系统会在gen目录中自动生成一个Iservice.Java文件

            4.定义的中转对象直接继承stub

            5.获取中转对象方式stub.asInterface()获取定义的中转对象

    进程和线程的区别:

        一个已经开启的应用程序就是一个进程.

        一个开启的应用程序中可以有多个线程同时在应用程序里面执行

    bind方式开启服务和start方式开启服务的区别:

        start:服务一旦被开启就会一直在后台执行,知道用户手动停止或者我们执行stopservice方法

        bind:当前Activity销毁的时候服务跟着销毁;服务职能被解绑一次,多次解绑会报异常;bind方式开启服务,服务在设置页面看不到,相当于一个隐形的服务

ContentProvider(内容提供者):

    通过内容提供者暴漏的数据,我们都是通过内容解析者去获取数据.

    内容提供者实现步骤:

        1.写个类继承ContentProvider.

        2.定义urimatcher.

private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);

        3.添加匹配规则:

 static{
        // authority 要和你在清单文件里面配置一样
        sURIMatcher.addURI("清单文件中配置参数相同", "query",QUERYSUCESS);
}

        4.到清单文件中配置.

        5.暴漏方法.

        6.其它应用通过内容解析者去获取数据.

    contentObserver(内容观察者):

        contentObserver(内容观察者):不是四大组件,不需要在清单文件中配置

        contentProvider(内容提供者):是四大组件,需要在清单文件中配置

多媒体-图片:

    图片的大小 = 图片的总像素*每个像素的大小

    单色:每个像素最多表示两种颜色,只需要使用长度为1的二进制表示即可,每个像素占1/8byte

    16色:每个像素最多表示16种颜色,使用长度为4的二进制表示,每个像素占1/2byte

    256色:每个像素最多表示256种颜色使用长度为8的二进制表示,每个像素占1byte

    24位:可以表示1600多万种颜色 RGB(R:1byte G:1byte B:1byte) 每个像素占3byte

    图片的格式:

        png:图片以高质量保存图片,用于计算机或者网络

        jpg:图片以良好的质量保存,用于计算机或者网络

        bmp:以高质量保存,用于计算机

    OOM(OutOfMemoryError)内存溢出异常:

        当内存不够用时会造成OOM异常,一般加载图片时比较常见(因为Android中使用RGB不足以表示颜色,在Android下使用ARGB表示颜色,每个像素占4byte).

    mediaplayer控件:

    srufaceView控件:

        一个重量级控件,内部维护一个双缓冲机制AB,一个负责加载数据,一个负责显示数据,它可以在子线程直接更新UI

    videoView控件:

        videoView是对surfaceView和mediaplayer进行封装.

Fragment控件:

    Fragment:英语片段的意思,Fragment是Activity的一个组成部分,不能独立存在,只能依赖于Activity而存在

    Fragment通过公共的桥梁Activity实现Fragment之间的通信

    Fragment生命周期:

        onAttach:Fragment依附于Activity时调用

        onCreate:初始化Fragment时调用

        onCreateView:绑定布局文件

        onActivityCreate:通知Fragment,它所依附的Activity已经onCrete了

        onViewStateRestored:通知Fragment,View状态已经被保存

        onStart:Fragment可见的时候调用

        onResume:Fragment获取焦点的时候调用

        onPause:Fragment失去焦点的时候调用

        onStop:Fragment不可见的时候调用

        onDestroyView:Fragment可以在方法中清除自身的View状态

        onDestroy:清除掉Fragment时调用

        onDetach:Fragment解除依附时调用

        Fragment生命周期很多,但常用的有onCreateView() onDestroy()和onCreate

Menu菜单:

    添加Menu菜单的两种方式:

        1.布局文件添加Menu菜单

        getMenuInflater().inflate(R.menu.main, menu);//要加载Menu下的布局文件

        2.代码添加Menu菜单

            menu.add(0,1,0,"前进");

    当想自定义Menu菜单的View时要重写onMenuOpened(),并把它的返回值改为false

    想在哪个Activity里面有菜单就在哪个Activity里面重写onCreateOptionsMenu方法,要知道具体点击的是哪个条目重写onOptionsItemSelected()

AutoCompleteTextView控件:

    一个联想单词的控件,它会使用近似联想的展示和当前输入字符串接近的字符串

Android中Animation(动画):

    帧动画(Frame Animation):将多张图片在规定的时间内,用相同的的频率,展示所有图片

    补间动画(Tween Animmation):通过在两个关键帧之间补充渐变的动画效果实现动画,相对于帧动画节省空间,但不能改变控件的真是坐标.

        AlphaAnimation(透明动画):看见到看不见,渐变效果

        TranslateAnimation(位移动画):指定开始和结束坐标,渐变效果

        ScaleAnimation(缩放动画):指定缩放参照坐标,实现缩放

        RotateAnimation(旋转动画):指定旋转参考坐标,实现旋转

        AnimationSet(组合动画/动画的合集):

    属性动画(ObjectAnimation):会改变控件的真实坐标,xml定义属性动画要在animator目录下创建animator目录

版本控制:常用的帮版本控制(CVS/SVN/ClearCase/VSS/git)

    


















































































你可能感兴趣的:(Android基础)