写点什么

月薪 20+ 的 Android 面试都问些什么?,android 实战开发记账本 app 视频

用户头像
Android架构
关注
发布于: 17 小时前

}


@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//在 onCreate 中初始化 activityWeakReference = new WeakReference<MainActivity>(this);myHandler = new MyHandler(activityWeakReference);


myHandler.sendEmptyMessage(1);mTextView = (TextView) findViewById(R.id.tv_test);}


参考博文http://blog.csdn.net/ucxiii/article/details/50972747


2.onNewIntent()的调用时机


解析:


在 Android 应用程序开发的时候,从一个 Activity 启动另一个 Activity 并传递一些数据到新的 Activity 上非常简单,但是当您需要让后台运行的 Activity 回到前台并传递一些数据可能就会存在一点点小问题。


首先,在默认情况下,当您通过 Intent 启到一个 Activity 的时候,就算已经存在一个相同的正在运行的 Activity,系统都会创建一个新的 Activity 实例并显示出来。为了不让 Activity 实例化多次,我们需要通过在 AndroidManifest.xml 配置 activity 的加载方式(launchMode)以实现单任务模式,如下所示:


<activity android:label="@string/app_name"


android:launchmode="singleTask"android:name="Activity1">


</activity>


launchMode 为 singleTask 的时候,通过 Intent 启到一个 Activity,如果系统已经存在一个实例,系统就会将请求发送到这个实例上,但这个时候,系统就不会再调用通常情况下我们处理请求数据的 onCreate 方法,而是调用 onNewIntent 方法


答案:


前提:ActivityA 已经启动过,处于当前应用的 Activity 堆栈中;当 ActivityA 的 LaunchMode 为 SingleTop 时,如果 ActivityA 在栈顶,且现在要再启动 ActivityA,这时会调用 onNewIntent()方法


当 ActivityA 的 LaunchMode 为 SingleInstance,SingleTask 时,如果已经 ActivityA 已经在堆栈中,那么此时会调用 onNewIntent()方法


当 ActivityA 的 LaunchMode 为 Standard 时,由于每次启动 ActivityA 都是启动新的实例,和原来启动的没关系,所以不会调用原来 ActivityA 的 onNewIntent 方法,仍然调用的是 onCreate 方法


以下是代码实例


1.设置 MainActivity 的启动模式为 SingleTask(栈内复用)


<activityandroid:name=".MainActivity"android:launchMode="singleTask"><intent-filter><action android:name="android.intent.action.MAIN" />


<category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>


2.MainActivity 中重写 onNewIntent 方法


public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";private Button mButton;


@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mButton = (Button) findViewById(R.id.forward_btn);mButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {startActivity(new Intent(MainActivity.this, Main2Activity.class));}});


@Overrideprotected void onNewIntent(Intent intent) {Toast.makeText(this, "onnewIntent", Toast.LENGTH_SHORT).show();Log.i(TAG, "onNewIntent: i done....");}


3.Main2Actvity 执行点击跳转,MainActivity 被复用,执行 onNewIntent 方法


public class Main2Activity extends AppCompatActivity {private Button mButton;


@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);


mButton = (Button)findViewById(R.id.btn);


mButton.setOnClickListener(new View.OnClickListener() {@Override


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


public void onClick(View view) {startActivity(new Intent(Main2Activity.this,MainActivity.class));finish();}});


3.RecyclerView 相比 ListView 有哪些优势


解析:


首先需要解释下 RecyclerView 的这个名字了,从它类名上看,RecyclerView 代表的意义是,我只管 Recycler View,也就是说 RecyclerView 只管回收与复用 View,其他的你可以自己去设置。可以看出其高度的解耦,给予你充分的定制自由(所以你才可以轻松的通过这个控件实现 ListView,GirdView,瀑布流等效果)


其次 RecyclerView 提供了添加、删除 item 的动画 效果,而且可以自定义


RecyclerView 相比 ListView 优势在于可以轻松实现:


ListView 的功能 GridView 的功能横向 ListView 的功能横向 ScrollView 的功能瀑布流效果便于添加 Item 增加和移除动画


不过一个挺郁闷的地方就是,系统没有提供 ClickListener 和 LongClickListener。不过我们也可以自己去添加,只是会多了些代码而已。实现的方式比较多,你可以通过 mRecyclerView.addOnItemTouchListener 去监听然后去判断手势,


当然你也可以通过 adapter 中自己去提供回调


4.谈一谈 Proguard 混淆技术


答案:


Proguard 技术有如下功能:


压缩 --检查并移除代码中无用的类优化--对字节码的优化,移除无用的字节码混淆--混淆定义的名称,避免反编译


预监测--在 java 平台对处理后的代码再次进行检测


代码混淆只在上线时才会用到,debug 模式下会关闭,是一种可选的技术。


那么为什么要使用代码混淆呢?


因为 Java 是一种跨平台的解释性开发语言,而 java 的源代码会被编译成字节码文件,存储在.class 文件中,由于跨平台的需要,java 的字节码中包含了很多源代码信息,诸如变量名、方法名等等。并且通过这些名称来访问变量和方法,这些变量很多是无意义的,但是又很容易反编译成 java 源代码,为了防止这种现象,我们就需要通过 proguard 来对 java 的字节码进行混淆,混淆就是对发布的程序进行重新组织和处理,使得处理后的代码与处理前的代码有相同的功能,和不同的代码展示,即使被反编译也很难读懂代码的含义,哪些混淆过的代码仍能按照之前的逻辑执行得到一样的结果。


但是,某些 java 类是不能被混淆的,比如实现了序列化的 java 类是不能被混淆的,否则反序列化时会出问题。


下面这类代码混淆的时候要注意保留,不能混淆。


Android 系统组件,系统组件有固定的方法被系统调用。被 Android Resource 文件引用到的。名字已经固定,也不能混淆,比如自定义的 View 。Android Parcelable ,需要使用 android 序列化的。其他 Anroid 官方建议 不混淆的,如 android.app.backup.BackupAgentHelperandroid.preference.Preferencecom.android.vending.licensing.ILicensingServiceJava 序列化方法,系统序列化需要固定的方法。枚举 ,系统需要处理枚举的固定方法。本地方法,不能修改本地方法名 annotations 注释数据库驱动有些 resource 文件


5.ANR 出现的场景及解决方案


在 Android 中,应用的响应性被活动管理器(Activity Manager)和窗口管理器(Window Manager)这两个系统服务所监视。当用户触发了输入事件(如键盘输入,点击按钮等),如果应用 5 秒内没有响应用户的输入事件,那么,Android 会认为该应用无响应,便弹出 ANR 对话框。而弹出 ANR 异常,也主要是为了提升用户体验。


解决方案是对于耗时的操作,比如访问网络、访问数据库等操作,需要开辟子线程,在子线程处理耗时的操作,主线程主要实现 UI 的操作


6.Android Handler 的机制和原理


主线程使用 Handler 的过程


首先在主线程创建一个 Handler 对象 ,并重写 handleMessage()方法。然后当在子线程中需要进行更新 UI 的操作,我们就创建一个 Message 对象,并通过 handler 发送这条消息出去。之后这条消息被加入到 MessageQueue 队列中等待被处理,通过 Looper 对象会一直尝试从 Message Queue 中取出待处理的消息,最后分发会 Handler 的 handler Message()方法中。


7.简述项目中对于内存优化的几个细节点


答案:


1.当查询完数据库之后,及时关闭 Cursor 对象。


2.记得在 Activity 的 onPause 方法中调用 unregisterReceiver()方法,反注册广播


3.避免 Content 内存泄漏,比如在 4.0.1 之前的版本上不要讲 Drawer 对象置为 static。当一个 Drawable 绑定到了 View 上,实际上这个 View 对象就会成为这个 Drawable 的一个 callback 成员变量,上面的例子中静态的 sBackground 持有 TextView 对象 lable 的引用,而 lable 只有 Activity 的引用,而 Activity 会持有其他更多对象的引用。sBackground 生命周期要长于 Activity。当屏幕旋转时,Activity 无法被销毁,这样就产生了内存泄露问题。


4.尽量不要在 Activity 中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用,当非静态内部类的引用的声明周期长于 Activity 的声明周期时,会导致 Activity 无法被 GC 正常回收掉。


5.谨慎使用线程 Thread!!这条是很多人会犯的错误: Java 中的 Thread 有一个特点就是她们都是直接被 GC Root 所引用,也就是说 Dalvik 虚拟机对所有被激活状态的线程都是持有强引用,导致 GC 永远都无法回收掉这些线程对象,除非线程被手动停止并置为 null 或者用户直接 kill 进程操作。所以当使用线程时,一定要考虑在 Activity 退出时,及时将线程也停止并释放掉


6.使用 Handler 时,要么是放在单独的类文件中,要么就是使用静态内部类。因为静态的内部类不会持有外部类的引用,所以不会导致外部类实例的内存泄露


8.TCP 和 UPD 的区别以及使用场景


TCP 与 UDP 基本区别


1.基于连接与无连接


2.TCP 要求系统资源较多,UDP 较少;3.UDP 程序结构较简单 4.流模式(TCP)与数据报模式(UDP);5.TCP 保证数据正确性,UDP 可能丢包 6.TCP 保证数据顺序,UDP 不保证


UDP 应用场景:


1.面向数据报方式 2.网络数据大多为短消息 3.拥有大量 Client4.对数据安全性无特殊要求 5.网络负担非常重,但对响应速度要求高


9.简述一个设计模式的概念,并简要谈谈 framework 层哪些地方用到了什么设计模式


**单例模式: **单例模式是一种对象创建模式,它用于产生一个对象的具体实例,它可以确保系统中一个类只产生一个实例。


**适配器模式: **将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)


**装饰模式:**动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
月薪20+的Android面试都问些什么?,android实战开发记账本app视频