常用知识点及常见问题

1.使用sharedPreferences保存数据
private void putShareData() {    
SharedPreferences sharedPreferences = getSharedPreferences("phoneNum", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString("devicePhone", AppInfo.phoneNumber);
editor.putString("localPhone", localPhone);    
editor.commit();
}
private void getSharedData() {    
SharedPreferences sharePreference = getSharedPreferences("phoneNum", MODE_PRIVATE);    //可以使用PreferenceManager.getDefaultSharedPreferences获取实例
AppInfo.phoneNumber = sharePreference.getString("devicePhone", "");    localPhone = sharePreference.getString("localPhone", "");
}
2.Android视频
  • ijkplayer 是一个基于 ffplay 的轻量级 Android/iOS 视频播放器。实现了跨平台功能,API易于集成;编译配置可裁剪,方便控制安装包大小;支持硬件加速解码,更加省电;提供Android平台下应用弹幕集成的解决方案,此方案目前已用于美拍和斗鱼 APP。
  • Vitamio 能够流畅播放720P甚至1080P高清MKV,FLV,MP4,MOV,TS,RMVB等常见格式的视频,还可以在 Android 与 iOS 上跨平台支持 MMS, RTSP, RTMP, HLS(m3u8) 等常见的多种视频流媒体协议,包括点播与直播。
3.自定义view
  • 自定义view步骤
    1.了解view的工作原理
    2.编写继承view的基类
    3.为自定义view类增加属性
    4.绘制控件
    5.响应用户消息
    6.自定义回调函数
  • 实现方式
    • 继承已有的控件实现
    • 组合已有的控件实现
    • 完全自定义控件
  • view绘制流程
  • Constructors 构造函数内进行一些参数的初始化,比如自定义属性
  • onMeasure 测量View及其子View的宽高属性,这里是属性,而不仅仅是宽高的值
  • onLayout 确定View及其子View的布局位置,也就是View及其子View在父容器中的坐标位置
  • onSizeChanged View的大小发生改变时,将调用此函数,一个View的大小在绘制过程中可能发生改变,比如父View
  • onDraw View的内容绘制部分,系统会提供给我们一块画布
4.android:textAppearance

设置文字外观。如 “?android:attr/textAppearanceLargeInverse”这里引用的是系统自带的一个外观,?表示系统是否有这种外观,否则使用默认的外观。可设置的值如下:textAppearanceButton/textAppearanceInverse/textAppearanceLarge/textAppearanceLargeInverse/textAppearanceMedium/textAppearanceMediumInverse/textAppearanceSmall/textAppearanceSmallInverse

5.制造延迟效果
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mMainPresenter.loadData();
}
}, 2000);
6.android 状态栏颜色

windowBackground设为白色,colorPrimaryDark设为透明时,个别机型会出现状态栏白色,状态栏的字体颜色也默认是白色,所以造成无法分辨和查看!
解决办法:colorPrimaryDark设为不透明,在布局中设置背景颜色控制状态栏颜色

7.Java获取时间格式
public static String getCurrentTime(String pattern){
        SimpleDateFormat sdf=new SimpleDateFormat(pattern);
        return sdf.format(new Date());
    }
/**
 *                          HH:mm    15:44
 *                         h:mm a    3:44 下午
 *                        HH:mm z    15:44 CST
 *                        HH:mm Z    15:44 +0800
 *                     HH:mm zzzz    15:44 中国标准时间
 *                       HH:mm:ss    15:44:40
 *                     yyyy-MM-dd    2016-08-12
 *               yyyy-MM-dd HH:mm    2016-08-12 15:44
 *            yyyy-MM-dd HH:mm:ss    2016-08-12 15:44:40
 *       yyyy-MM-dd HH:mm:ss zzzz    2016-08-12 15:44:40 中国标准时间
 *  EEEE yyyy-MM-dd HH:mm:ss zzzz    星期五 2016-08-12 15:44:40 中国标准时间
 *       yyyy-MM-dd HH:mm:ss.SSSZ    2016-08-12 15:44:40.461+0800
 *     yyyy-MM-dd'T'HH:mm:ss.SSSZ    2016-08-12T15:44:40.461+0800
 *   yyyy.MM.dd G 'at' HH:mm:ss z    2016.08.12 公元 at 15:44:40 CST
 *                         K:mm a    3:44 下午
 *               EEE, MMM d, ''yy    星期五, 八月 12, '16
 *          hh 'o''clock' a, zzzz    03 o'clock 下午, 中国标准时间
 *   yyyyy.MMMMM.dd GGG hh:mm aaa    02016.八月.12 公元 03:44 下午
 *     EEE, d MMM yyyy HH:mm:ss Z    星期五, 12 八月 2016 15:44:40 +0800
 *                  yyMMddHHmmssZ    160812154440+0800
 *     yyyy-MM-dd'T'HH:mm:ss.SSSZ    2016-08-12T15:44:40.461+0800
 * EEEE 'DATE('yyyy-MM-dd')' 'TIME('HH:mm:ss')' zzzz    星期五 DATE(2016-08-12) TIME(15:44:40) 中国标准时间
 */
7.程序的复杂度
  • 时间复杂度是总运算次数表达式中,受n的变化影响最大的那一项(不含系数)
  • 空间复杂度是一个算法运行过程中临时占用存储空间大小的度量
8. 关于compileSdkVersion, minSdkVersion 和 targetSdkVersion
  • compileSdkVersion,只有在编译时使用的api版本,尽可能使用较新的版本,可以避免新弃用的api
  • minSdkVersion决定了应用运行的最低要求,使用第三方库时,最低api要比第三方库的最低api大
  • targetSdkVersion 使应用向前兼容,使用新添加的功能,尽可能使用最新的版本
  • 理想情况下应该是这样的:minSdkVersion (lowest possible) <= targetSdkVersion == compileSdkVersion (latest SDK)
9.Java设计模式
  • 构造者模式(将一个复杂对象的构造跟表示分离,通过相同的构造过程,创建不同的表示,例如:AlertDialog.Builder builder = new AlertDialog.Builder(this);
  • 原型模式 (用原型实例指定创建对象的类型,通过对原型的拷贝创建新的对象。使用方法:实现Cloneable接口,重写clone()方法。注意:使用原型模式不会创建新的对象,仅仅拷贝,节省创建对象对资源的消耗,深拷贝(拷贝时,数组,对象,集合需要自己实现进行拷贝)浅拷贝(基本数据类型会自动拷贝))
  • 简单工厂模式,工厂模式,抽象工厂模式 (简单工厂:可以理解为一个创建对象的工具类。工厂模式:定义一个创建对象的接口,由子类来决定实例化哪一个类,工厂方法把类的实例化推迟到子类。抽象工厂模式:包含多个工厂类)
  • 策略模式(有一系列算法,将每一个算法封装起来,每个算法之间可以相互替换。策略模式与工厂模式实现相同)
  • 状态模式 (在状态模式中,行为是由状态来决定的,不同的状态对应不同的行为。状态模式与工厂模式实现相同,表达的目的不一样,一个关注对象的创建,一个关注行为的封装。减少耦合,少写if else 语句)
  • 责任链模式 (使多个对象都有机会处理请求,从而避免请求的发送者与接受者直接的耦合关系,将这些对象连成一条链,并延这条链传递请求,直到有对象处理请求为止。减少耦合,少写if else 语句)
  • 解释器模式 (给定一个语言,定义它的语法,并定义它的解释器,这个解释器用于解析语言。)
  • 命令模式 (把请求或操作封装为对象,允许使用不同的请求把客户端参数化,对请求排队或记录请求日志,可以提供命令的撤销和恢复功能。好处:降低耦合性,易扩展)
  • 观察者模式 (多个观察者监听被观察者,被观察者状态发生改变时通知观察者。观察者模式可以用接口回调来实现)
  • 备忘录模式 (在不破坏封闭的情况下,捕获一个对象的状态,在对象之外保存这个状态,以后就可以把对象恢复到这个状态。Android 中Activity的onSaveInstanceState和onRestoreInstanceState就使用了备忘录模式,用于保存和恢复)
  • 迭代器模式 (用一种方法顺序地访问聚合对象中的元素,而不暴露对该对象的内部表示。就像java中的Collection,List、Set、Map等,这些集合都有自己的迭代器)
  • 模板方法模式 (定义一个算法框架,使一些方法延迟到子类中执行,使得子类不改变算法的结构即可重定义算法的某些特定功能。用于对多次使用的算法封装起来,实现算法不变的部分,将可变的部分留给子类去实现)
  • 访问者模式 (封装一些作用于数据结构元素之上的一些方法,一旦这些方法需要改变时,接受这个操作的数据结构保持不变)
  • 中介者模式 (用一个中介对象封装一系列对象的交互,使得各个对象不需要显式引用,可以松散解耦。MVP架构中P层就使用了中介者模式进行M,V层的分离)
  • 外观模式 (为子系统中的一组方法提供了统一的访问接口,这个接口使得子系统更容易访问和使用)
  • 代理模式 (通过代理对象访问目标对象。好处是:在访问目标对象的基础上,增加额外的功能,扩展额外的公告,符合软件设计的开闭原则。主要分为:静态代理,动态代理)
  • 装饰者模式 (动态地为一个类添加功能。相对继承父类来扩展功能,装饰者模式能减少子类的创建,可以动态加入。装饰者模式与代理模式相比:装饰者模式侧重于对装饰的对象功能扩展,代理模式侧重于对访问对象施加控制)
  • 组合模式 (将对象组合成树形结构,以表示 部分与整体 层次结构,使得用户对单个对象和整体对象的使用具有一致性。)
  • 适配器模式 (把一个类接口转换成客户期待的另一个接口,使原本由于接口不相兼容不能工作的两个类可以一起工作。当想使用一个既有类,既有类不满足当前类的功能时,可以考虑用适配器模式)
  • 享元模式 (一个系统中可能有多个相同的对象,只共享一份对象就可以了,不用实例化每个对象。String类就使用了享元模式)
  • 桥接模式 (把抽象跟实现分开,使它们能够独立的变化。)
10.Android studio导入项目一直停留在Build界面

主要原因:当前要打开项目中的gradle版本 与 电脑环境中gradle版本不一致,或者本地找不到,然后远程下载不下来 导致一直停留在Build界面
解决办法:查看能打开的项目,进入 gradle/wrapper/gradle-wrapper.properties 复制文件最后一行到不能打开的项目中,保存即可打开。

11.频繁gc会导致界面卡顿,或者卡死

频繁gc的一个原因可能是:定时器轮询任务中不断创建对象

12.TextView文字超过显示范围时,自动滚动显示


        

有多个时要设置:

textView.setSelected(true);

13.使用弱引用来解决内存泄漏

  • 内存泄漏:静态变量,缓存,生命期长的对象,引用了其他对象,导致被引用的对象长时间得不到GC释放,导致内存泄漏
  • 弱引用:弱引用的对象会被GC,在需要的时候释放内存
  • 举例(使用静态类使内部类跟外部类无关,但是操作外部类的方法不可能全部申明静态的,所以要弱引用外部对象)
private Handler mHandler = new MyHandler(this);
private static class MyHandler extends Handler{

        private final WeakReference activityWeakReference;

        public MyHandler(VoicePagingActivity voicePagingActivity) {
            activityWeakReference = new WeakReference<>(voicePagingActivity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            VoicePagingActivity activity = activityWeakReference.get();
            if (activity == null){
                return;
            }
            activity.soundRecordView.setDecibel(s);
            activity.mHandler.sendEmptyMessageDelayed(0,5);
        }
    }

14.RecyclerView内部BUG:引起IndexOutOfBoundsException异常

  • 主要原因:数据集合不同步,在改变list时没有及时进行notifyDataChange
  • 解决办法:1.防止不同步(注意集合引用) 2.重写RecyclerView的LinearLayoutManager捕获异常
    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        try {
            super.onLayoutChildren(recycler, state);
        } catch (IndexOutOfBoundsException e) {
            e.printStackTrace();
        }
    }

15.捕获异常

  • 当某个程序执行,调用时可能会产生各种各样的异常,若不对某个异常进行处理,最好用全局异常捕获,例如:
try {
           isTrue =   myApplication.getOneLineAudioPrx().StopProgramCurProgramByTerminal(vDstTerminalIDS);
    } catch (Exception e) {
                e.printStackTrace();
            }
  • 捕获到异常后不会退出当前的函数调用,会继续往下执行,必要的时候在catch块中进行return处理

16.对EditText做输入限制

public static void setEditTextInput(final EditText editText) {
        InputFilter filter = new InputFilter() {
            @Override
            public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
                //输入字符数限制
                try {
                    if ((editText.getText().toString() + source.toString()).getBytes("utf-8").length > 32) {
                        return "";
                    }
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                //过滤空格跟换行符
                if (source.equals(" ") || source.toString().contentEquals("\n")) {
                    Log.e("setEditTextInputSpace1", source.toString());
                    return "";
                }

                //过滤特殊字符
                String speChat = "[`~!@#$%^&*()+=|{}':;',\\\\.<>/?~!@#¥%……&*()——+|{}【】‘;:”“'。,、?]";
                //String speChat="\\\\";(过滤\)
                Pattern pattern = Pattern.compile(speChat);
                Matcher matcher = pattern.matcher(source.toString());
                if (matcher.find()) return "";
                else return null;
            }
        };
        editText.setFilters(new InputFilter[]{filter});
    }

17.大小端问题

  • 大小端跟cup架构有关,跟语言也有关,一般arm,x86平台是小端,Java跟平台无关,默认是大端,网络字节序一般是大端传输
  • 大端是高位数据存放高地址(后面),小端是低位数组放在前面(低地址)
  • 判断是否大小端,可以将0x01右移八位是否等于1,等于就是小端
  • 大小端是面向多字节数据,单字节,字符串一般不用考虑

18.RecyclerView item不复用

在200多个item时导致界面加载很慢,点击反馈也很慢,无论加载还是点击item都会调用item总数个onBindViewHolder().经过各种尝试(放入一个新project各种测试))发现导致的原因是:界面布局问题。RecyclerView外层有两个LinearLayout再外层是SwipeRefreshLayout,把SwipeRefreshLayout直接包裹RecyclerView问题解决

19.链式调用的写法

  • 定义Class
public class SessionBuilder {
//最好定义单例模式
public final static SessionBuilder getInstance() {
        if (sInstance == null) {
            synchronized (SessionBuilder.class) {
                if (sInstance == null) {
                    SessionBuilder.sInstance = new SessionBuilder();
                }
            }
        }
        return sInstance;
    }   

public SessionBuilder setCallback(Session.Callback callback) {
        mCallback = callback;
        return this;
    }

public SessionBuilder setContext(Context context) {
        mContext = context;
        return this;
    }

public Session build() {
        session = new Session();
                //session 初始化...
                return session
}
  • 调用
session = SessionBuilder.getInstance()
                .setCallback(this)
                .setContext(MyApplication.getContext().getApplicationContext())
                .setDestinationPort(port)
                .setAudioEncoder(SessionBuilder.AUDIO_AAC)
                .setAudioQuality(new AudioQuality(48000, AudioFormat.ENCODING_PCM_16BIT, AudioFormat.CHANNEL_IN_STEREO, 32000))
                .build();
20.TextView显示问题
  • singleLine 是用来限制行数,maxLines 用来限制高度
  • 在RecyclerView中使用TextView设置singline属性,同时操作多个item时容易造成TextView不显示的问题;用maxLines 替代,但是当text中数字,英文字符,特殊字符混合时会造成TextView不满一行时自动换行,显示不全;解决办法:自定义控件继承TextView,重写onDraw,使用drawText进行绘制。
21.AsyncTask 执行后没有立即执行doInBackground()方法
  • 原因:Android3.0 之后AsyncTask 调用execute()方法,线程串行执行,只要前一个任务没执行完,当前提交的任务就会被阻塞
  • 解决办法:需要并行执行时使用AsyncTask 的executeOnExecutor()方法,参数可以是:AsyncTask.THREAD_POOL_EXECUTOR,或者定义自己的线程池:ExecutorService executorService = Executors.newFixedThreadPool(5);
22.在MAC 系统下安装FFMPEG同时安装FFPLAY
  • brew reinstall ffmpeg --with-sdl2(此命令可以保证成功安装ffplay)
  • 上面安装失败可以先尝试brew install ffmpeg

23.TCP & UDP

  • TCP 面向流的通信,发送端可以任意send,接收端可以recv任意大小的数据
  • UDP面向无连接,发送端发送过快,接收端会接收不过来,导致丢包的出现(优化办法:1.请求一个包发送一次;2.控制接收发送的频率,接收后最好不做耗时的操作以防影响下次接收)

24.Activity全屏弹出Dialog导致导航栏,状态栏显示

  • 弹出Dialog时禁用获取焦点可以解决
  • 在dialog.show()之前调用:
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);  //将会造成底部的view仍然可点击
  • 必要的时候再做一下theme设置:
true
@null

25.关于组播

  • 要想能收到组播,或者抓包工具能抓到组播包,必须本机加入组播
  • 用组播socket可以收到组播包,也能收到单播包
  • 用组播socket可以发送组播包,也能发送单播包

26.关于IntentService

  • 第一次startService()时执行onHandleIntent()方法,随后再次调用startService(),执行onHandleIntent()(调用onHandleIntent执行完的情况下)或者onStartCommand()(调用onHandleIntent没执行完的情况下)
  • onHandleIntent()本身就是一个后台线程,此线程执行结束,IntentService自动停止释放
  • 每次启动startService()都会加入队列,瞬加启动太多次得不到及时处理会造成多个任务阻塞(解决方法:可以创建自己的队列进行监测)

27.APP长连接在断网时处理

  • 针对APP启动时创建的长连接套接字,运行中途断网重新联网后最好重新进行创建长连接,尤其是当长连接在一个服务,一个线程阻塞运行时,断网后已经异常退出
  • APP启动时没连上网,中间连上网,同样要重启长连接

27.EditText限制输入类型为IP

  android:inputType="number"
  android:digits="0123456789."

28.对大数字格式化

//@param pattern可以为:",###"
public static String parseNumber(String pattern, BigDecimal bd) {
        DecimalFormatSymbols unusualSymbols = new DecimalFormatSymbols(Locale.CHINA);
        unusualSymbols.setGroupingSeparator(' ');
        DecimalFormat decimalFormat = new DecimalFormat(pattern, unusualSymbols);
        return decimalFormat.format(bd);
    }

29.判断android系统是否root

/** 
     * 判断手机是否拥有Root权限。 
     * @return 有root权限返回true,否则返回false。 
     */  
    public boolean isRoot() {  
        boolean bool = false;  
        try {  
            bool = new File(“/system/bin/su”).exists() || new File(“/system/xbin/su”).exists();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return bool;  
    }  

30.Android studio 关于Git使用

  • 搭环境(git安装,IDE环境配置,针对Git,Github)
  • 分享项目到Github,别人可以进行clone,若要push则项目所在的Github设置使用ssh(别人可以直接提交代码到分支而不用审核),同时别人要把本地电脑的ssh key 加入到项目所在的账号
  • commit push pull (commit只会提交到本地,push才能推到分支,pull拉取远程有更新的分支)
  • 分支Branches (master作为主分支,有新的稳定版本发布时才从别的分支合并到主分支,通常会有个开发分支dev,专门做开发提交使用)
  • 平时开发通常设置本地分支,远程分支,为dev分支;当dev分支要合并到master分支时,把远程master分支检出到本地变为master分支;把远程分支dev合并到本地分支master,最后push即可

31.AsyncTask处理耗时任务简易写法

AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                //do time-consuming task
            }
        });

31.关于Android硬件加速

  • 硬件加速一帧的绘制由主线程,绘制线程一起配合执行;软件加速只由主线程完成,所有的渲染都在主线程完成
  • 硬件加速最终绘制交给GPU完成,软件加速最终绘制由CPU完成

32.Timer弊端

  • 向前修改系统时间导致Timer来不了,向后修改系统时间导致Timer来的特别慢,主要原因Timer的机制问题导致,Timer以系统时间System.currentTimeMillis()为基准,修改了系统时间System.currentTimeMillis()也会更改,推荐使用:ScheduledExecutorService
  • 第一个任务没执行完时会一直阻塞后面的任务,原因是:Timer是一种单线程调度的任务队列模型

33.字符串资源里变量替换

  • 字符串定义:第%1$s页
  • 代码中获取:String page = getString(R.string.page,"345");

34.关于Android系统

  • 微内核:在核心的基础功能:内存管理,进程管理等功能上加入其他功能模块,这些模块可以是单独进程,不影响系统的核心功能;微内核的系统有鸿蒙OS;使用微内核的好处是:当一个功能模块出问题时不影响系统的整体运行,弊端是IPC通信开销没有进程内函数的直接调用开销高
  • 宏内核:与微内核相反,把所有的东西都塞到内核里,共享同一块内存空间;linux内核用的就是宏内核
  • 混合内核:揉和了两种内核的特性
  • Android framework层中各个功能都是一个独立的进程,功能模块之间通过IPC通信,从这个角度看:Android系统是微内核
  • Android系统发布更新过程:AOSP ==> 芯片厂商(兼容性适配,加入feature)==> 手机厂商(兼容性适配,加入feature)==> android手机
  • Android的成功源于在framework层封装提供了大量常用功能,又把java作为APP编写语言吸引了大量Java开发人员进行开发,同时使用linux kernal使得大量硬件厂商几乎0成本的驱动开发适配

35.SparseArray源码解析

  • SparseArray相对HashMap存储效率高,但SparseArray使用二分法查找键,导致存储大量数据时查找效率较低
  • 内部使用两个一维数组保存键和值,通过键值映射进行扩容和缩容

36. ViewStub

  • ViewStub 是一个看不见,没有大小,不占布局位置的View,用来懒加载布局。当ViewStub显示可见或inflate() 时就会加载布局并且替换ViewStub

37.Native代码中常见的:RefBase,sp,wp

  • RefBase在Android的C++部分,是所有类的基类
  • sp 强指针(strong pointer)
  • wp弱指针(Weak Pointer)引用对象不需要手动释放

38.关于Serializable,Parcelable

  • 都是用来进行序列化的接口,序列化:把对象转换为byte[],反序列化:把byte[]转换为对象;序列化的目的:1.进程间传递对象时,不能使用引用或指针传递对象,因为进程有自己的独立内存空间,同一个地址在不同的进程空间指向的内容不同(Activity之间传递对象需要实现序列化的接口,主要为了更好的兼容适配跨进程传递) 2.方便把对象中的字段,方法传递的同时,也方便保存到本地 3.网络传输
  • Serializable属于java api 中提供的接口,效率较低,不适合内存间数据传递,但适合序列化到本地
  • Parcelable属于Android api中提供的接口,效率较高,适合内存间数据传递,但不适合序列化到本地

你可能感兴趣的:(常用知识点及常见问题)