你的位置:首页 > 操作系统

[操作系统]Android 面试题及答案(2)


1.Activity相关。launchmode,OnSaveInstnceState,生命周期等。

 4种默认的launchmode,以及OnNewIntent的回调。

OnNewIntent->OnRestart->OnStart->onResume

OnActivity->OnResume.

OnNewIntent ,OnActivityResult?

OnNewIntent launchmode with singletask or singleInstance.

but if set these two mode. OnActivityResult will be called after startActivityforResult directly。

so normally,they can not called both.

OnSaveInstanceState:

在Activity这个方法的地方有一段描述:当activity将要被kill的时候,系统会开放这个借口供程序员调用

然后它会把bundle信息传递到OnCreate & Bundle里面。

这个方法一定会在OnStop之前被调用,but 与OnPause的顺序无法确定。

某些情况下,生命周期不会走到OnDestroy,但是有些资源需要释放。这时候,最好是事件驱动。

2.Fragment相关技术。

Fragment 的生命周期:Android四大组件之Activity & Fragement

Fragment和activity沟通,

fragmentmaneger.findFragmentById

fragmentmaneger.findFragmentByTag,

fragment之间的沟通,setArgument。

getActivity & addlistener等。

数据存储和恢复。onSaveInstanceState:Fragment的该func同Activity同步。

FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务

transaction.add() 

往Activity中添加一个Fragment

transaction.remove()

从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈(回退栈后面会详细说),这个Fragment实例将会被销毁。

transaction.replace()

使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体~

transaction.hide()

隐藏当前的Fragment,仅仅是设为不可见,并不会销毁

transaction.show()

显示之前隐藏的Fragment

detach()

会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。

attach()

重建view视图,附加到UI上并显示。

transatcion.commit()//提交一个事务

注意:常用Fragment的哥们,可能会经常遇到这样Activity状态不一致:State loss这样的错误。主要是因为:commit方法一定要在Activity.onSaveInstance()之前调用。

上述,基本是操作Fragment的所有的方式了,在一个事务开启到提交可以进行多个的添加、移除、替换等操作。

值得注意的是:如果你喜欢使用Fragment,一定要清楚这些方法,哪个会销毁视图,哪个会销毁实例,哪个仅仅只是隐藏,这样才能更好的使用它们。

其他问题:Android Fragment 真正的完全解析(下)

 FragmentTransaction.addToBackStack(String):如果是replace的方法,那么当前fragment会被remove掉,所有back的时候,fragment的状态不会保留,只会重新

创建。而如果是hide & add的方法,就会把之前的fragment重新attch上。

如果activity管理fragment,可以调用fragment的所有public方法。

可以通过findfragmentbyid & findfragmentbytag来定位fragment,然后同上。

fragment可以通过getactivity获得实例。 

当屏幕旋转是,fragment会被重复创建,这是时候如果使用OnCreate的bundle参数,就可以判断是否是第一次创建。

activity的默认实现bundle参数是有内容的。

3.序列化技术,Parcable & Serializable.

android 进程间通信数据(一)------parcel的起源

为什么要序列化:为了跨进程通信,应为进程间通信就是二进制格式,所以序列化可以通过反序列化,把数据还原。

parcable是内存机的序列化,所以速度快。

4.fastJson & GSon的使用

package com.joyfulmath.publibrary.json;import com.alibaba.fastjson.JSON;import com.joyfulmath.publicutils.utils.TraceLog;/** * @author deman.lu * @version on 2016-03-24 17:20 * 使用fastjson 来解析该问题 */public class JsonUtils {  public static <T> T parseObject(String jsonStr, Class<T> entityClass)  {    T ret = null;    try {      ret = JSON.parseObject(jsonStr,entityClass);    }catch (Exception e)    {      TraceLog.e("parseObject-something Exception with:" + e.toString());    }    return ret;  }  public static String toJSONString(Object obj) {    String ret = null;    try {      ret = JSON.toJSONString(obj);    } catch (Exception e) {      e.printStackTrace();    }    return ret;  }}

fastJson

 

5.多线程相关,包括handler,message looper. ExecutorService.

消息机制:android 进程/线程管理(一)----消息机制的框架 请看这个系列。

ExecutorService:线程池,可以提供关闭操作,等待关闭和直接关闭。

6.ImageLoader 原理,包括Glide,picasso,以及Fresco.

Picasso,square公司出品的图片加载器,内部使用OKHttp执行网络请求。

可以支持URL,FILE,数据库等路径的加载。图片不会缩放,

Picasso & Glide

首先Glide是基于Picasso的二次开发

with参数:Glide可以使用Activity、fragment等。所以它的加载可以和actiivty的生命周期绑定。

Glide默认图片ARGB_565 piocasso:ARGB_8888

Glide loading Gif but Picasso cannot. but Glide will using much memory with gif.

Glide will cache with size of imageview, so each size of imageview will contains one copy.

Picasso will only has one cahce copy with fullsize. so glide is faster than picasso.

Glide 有助于减少OOM的发生。

/** * Created by deman on 2016/3/30. */public interface IImageLoader {  void initLoader(Context context);  void load(String path, ImageView view, int width, int height);  void load(String path, ImageView view);}

IImageLoader
public class ImageLoadManger {  private IImageLoader iImageLoader = null;  private static ImageLoadManger sInstance = null;  public static synchronized ImageLoadManger getsInstance() {    if (sInstance == null) {      sInstance = new ImageLoadManger();    }    return sInstance;  }  /**   * initManager   * @param context context   */  public void initManager(Context context) {    iImageLoader = new PicassoImageLoader();    iImageLoader.initLoader(context);  }  /**   * load image with path   * @param path     path   * @param imageView imageView   */  public void load(String path, ImageView imageView) {    if(null == iImageLoader)    {      throw new RuntimeException("initManager has not been init");    }    iImageLoader.load(path, imageView);  }  /**   * load image with path   * @param path         path   * @param imageView     imageView   * @param width         width   * @param height        height   */  public void load(String path, ImageView imageView,int width,int height) {    if(null == iImageLoader)    {      throw new RuntimeException("initManager has not been init");    }    iImageLoader.load(path, imageView,width,height);  }}

ImageLoadManger
public class PicassoImageLoader implements IImageLoader {  Picasso picasso;  Context context;  private void init()  {    picasso = new Picasso.Builder(context).build();  }  @Override  public void initLoader(Context context) {    this.context = context;    init();  }  @Override  public void load(String path, ImageView view,int width,int height)  {    if(null == path)    {      throw new RuntimeException("uri is null!");    }    if(width == 0 || height == 0)    {      throw new RuntimeException("width & height is 0");    }    picasso.load(path)        .resize(width, height)        .into(view);  }  @Override  public void load(String path, ImageView view) {    if(null == path)    {      throw new RuntimeException("uri is null!");    }    picasso.load(path)        .into(view);  }}

PicassoImageLoader

Glide 500K,Picasso 100K

Fresco,是facebook开源的一套图片加载框架。它的使用是基于view级别的。SimpleDraweeView

Fresco, image pipline技术,三级缓存。所以不容易oom。

第一层。bitmap缓存:在5.0上,使用java heap,5.0一下,使用ashme内存,减少GC发生的概率。

app到后台,bitmap缓存被清空。

第二层,内存缓存。存放原始的压缩图片。

第三层,磁盘缓存,不会被清空。

Fresco对内存的节省效果很大,尤其是低端机,可以减少OOM的几率。

包比较大,而且使用起来也复杂。

7.Adapter 和 ListView 组合。

 

8.用户Cookie设计。token的流程包括登陆流程。

 登陆设计:

1)登陆跳转

首先是登陆到指定页面,比如MainActivity,

还有就是登陆后,回到上一页。

这2中需要在登陆的时候考虑到。

2)登陆的密码验证

密码加密后传输,以参数的形式。

API使用https请求。

登陆成功后,需要把userinfo存到本地,以便退出后,可以自动登陆。

3)自动登陆

token机制。每次登陆成功后,本地保存一个token信息,同时token可以保存过期的信息机制。

token过期后,所有先关API(需要验证token信息的),都会返回相同的code信息,然后统一处理。

弹出AlertDialog,让用户去判断是否需要登陆。

9.网络请求的封装。

Volley

Volley+okhttp

Retrofit

其中Retrofit+okHttp+Picasso 是square公司统一出品的。

主流的套路是,把每个框架都分开了,这样便于替换。

Retrofit+okHttp /Volley+Okhttp   add  fastjson , Glide/Fresco + buttnkinfe/dragger2/androidannotation + Rebotim.

Android 框架学习之 第一天 okhttp & Retrofit

10.Android & H5 的交互。

H5调用andoriod代码:

webSettings.setJavaScriptEnabled(true);

mWebView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");

js回调,@JavascriptInterface

android 调用JS

mWebView.loadUrl("javascript:wave()");

跳转协议:

当JS回调的时候,可以在shouldOverrideUrlLoading的时候

把URL配置成一个协议。

 

11.代码混淆。

 混淆的开启:androidstudio:

在gradle里面,有

  buildTypes {    release {      minifyEnabled false      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'    }  }

关键是minifyEnabled 编程true,混淆编译就会打开。

一般需要配置proguard-rules.pro

proguard4大过程:

压缩,字节码优化,混淆,预检。

proguard 可以配置版本:

proguard在sdk里面。

proguard可以配置过程:

-dontshrink 不压缩输入的类文件

-dontoptimize 不优化输入的类文件

-dontobfuscate 不混淆输入的类文件

12.android打包机制

包括sdk的命令。

Android原理揭秘之APk生成过程

打包过程:aapt用来生成资源文件R.java

java编译器->class文件,然后dex编译成.dex文件。

aapt放置的resource

打包成apk文件。

其他的最终会生成dex文件。+sign 过程,就是APK,当然可能需要压缩优化。

13.线上Crash分析并修复的能力。

首先是,对于没有处理的crash地方,通过UnCaughtExceptionHandler 来处理和收集日志。

三步:

收集日志并发送到服务器

提示用户处理

保存到SD

需要把proguardmapping文件保存下来,以便线上app分析问题。

14.内存泄露,包括内存优化,内存泄露的场景,以及MAT工具的使用。

 请参见Android 高级面试题及答案

 

15.Monkey机制。 Android开发如何对一款App进行monkey测试。

monkey就是对屏幕进行随机事件发送,一般次数都在1W次以上,主要测试结果是crash,ANR的事件。

monkey对象是apk

monkey的事件流是随机的。

monkey的文档:http://developer.android.com/guide/developing/tools/monkey.html

16.调试工具,包括DDMS,android studio的调试功能。

androidstudio工具:

AndroidMonitor:StartMethodTracing 测试method执行时间。

DDMS也有traceView,功能是一样的。

测试View的布局:hierachyviewer.

debug:高级调试功能:

Evaluate Expression:在run菜单下面,有这个选项,它的功能同watch差不多,但是它可以测试执行语句。

条件断点:在循环里面,你只对i=9感兴趣,你怎么办,在断点的位置,右击,出现条件。

日志断点:也是一个非常实用的技能,当我们某些情况下需要打印日志,但是每次编译非常耗时,这个时候,我们实用日志断点,可以打印日志,而

不修改源代码。在Debug窗口里面的console里面可以看到打印的日志。

方法断点:方法断点就是在函数名的这一样,断点,它会在函数入口和结束的地方断点。

异常断点:就是Run->View blockpoint->javaException.

属性断点:就是在某个属性被修改或者访问的时候,但是多线程复杂环境下,很难发现。Run->View blockpoint->javaFieldWatchpoints.

DDMS:Android Studio中怎么使用DDMS工具?

17.单元测试,Junit的使用,包括其他测试框架。

 

public class ExampleTest extends InstrumentationTestCase {  public void test() throws Exception {    final int expected = 1;    final int reality = 1;    assertEquals(expected, reality);  }  public void test_2() throws Exception{    final int expected = 2;    final int reality = 3;    assertEquals(expected,reality);  }}

需要在configration里面配置。

18.GIT的高级功能,Stage,rebase,revert,stash,cherry pick & sub module

stage是index区, 一个概念,对应work区 和history区

revert:就是把某次历史提交给取消掉,but它的提交记录会被保留,也就是可以提交到远程库。

reset:只是回退历史,回退内容可以被保留在work区域。

cherry pick:branch2 上的某条修改,需要merge到branch3上,but我只是需要这一条修改,用这条指令。

sub module:用处不是很大。

19.插件化编程。

专开一篇讲解

20.设计模式,对常见设计模式的熟悉程度。

 TBD.

21.热修复技术。

 TBD.

22.React +Native框架

TBD.

23.消息推送原理

 TBD.