java stopself_每日一题

生命周期

每日一题:横竖屏切换时候Activity的生命周期

不设置Activity的android:configChanges时,切屏会重新回掉各个生命周期,切横屏时会执行一次,切竖屏时会执行两次

设置Activity的android:configChanges=”orientation”时,切屏还是会调用各个生命周期,切换横竖屏只会执行一次

设置Activity的android:configChanges=”orientation |keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

每日一题:三种情况下Service的生命周期

1、startService / stopService

生命周期:onCreate --> onStartCommand --> onDestory

如果一个Service被某个Activity调用Context.startService 方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行,直到被调用stopService,或自身的stopSelf方法。

当然如果系统资源不足,Android系统也可能结束服务,还有一种方法可以关闭服务,在设置中,通过应用 --> 找到自己应用 --> 停止。

注意:

第一次startService会触发onCreate和onStartCommand,以后在服务运行过程中,每次startService都只会触发onStartCommand;不论startService多少次,stopService一次就会停止服务

2、bindService / unbindService

生命周期:onCreate --> onBind --> onUnbind --> onDestory

如果一个Service在某个Activity中被调用bindService方法启动,不论bindService被调用几次,Service的onCreate方法只会执行一次,同时onStartCommand方法始终不会调用。

当建立连接后,Service会一直运行,除非调用unbindService来解除绑定、断开连接或调用该Service的Context不存在了(如Activity被finish --- 即通过bindService启动的Service的生命周期依附于启动它的Context),系统会在这时候自动停止该Service。

注意:

第一次bindService会触发onCreate和inBind,以后在服务运行过程中,每次bindService都不会触发任何回调

一个应用程序有几个Context?为什么Activity、Service、Application都继承自Context,Context的作用是什么呢?

https://zhuanlan.zhihu.com/p/141126600

先说类关系:

Activity继承自ContextThemeWrapper,而Application和Service继承自ContextWrapper,很显然ContextThemeWrapper在ContextWrapper的基础上又做了一些操作使得Activity变得更强大

Context数量=Activity数量+Service数量+1

应用程序全局信息接口,访问资源、类、以及启动活动广播接受intent

3、混合型

当一个Service再被启动(startService)的同时又被绑定(bindService),该Service将会一直在后台运行,不管调用几次,onCreate方法始终只会调用一次,onStartCommand的调用次数与startService调用的次数一致(使用bindService方法不会调用onStartCommand)。同时,调用unBindService将不会停止Service,必须调用stopService或Service自身的stopSelf来停止服务。

UI

[每日一题]SurfaceView和View的最本质的区别

SurfaceView是在一个新起的单独线程中可以重新绘制画面,而view必须在UI的主线程中更新画面。

在UI的主线程中更新画面可能会引发问题,比如你更新的时间过长,那么你的主UI线程就会被你正在画的函数阻塞。

那么将无法响应按键、触屏等消息。

当使用SurfaceView由于是在新的线程中更新画面所以不会阻塞你的UI主线程。

但这也带来了另外一个问题,就是事件同步。

比如你触屏了一下,你需要SurfaceView中thread处理,一般就需要有一个event queue的设计来保存touchevent,这会稍稍复杂一点,因为涉及到线程安全。

协议

用UDP协议通讯时怎样得知目标机是否获得了数据包?

可以在每个数据包中插入一个唯一的ID,比如timestamp或者递增的int。

发送方在发送数据时将此ID和发送时间记录在本地。

接收方在收到数据后将ID再发给发送方作为回应。

发送方如果收到回应,则知道接收方已经收到相应的数据包;如果在指定时间内没有收到回应,则数据包可能丢失,需要重复上面的过程重新发送一次,直到确定对方收到。

tcp三次握手的过程,accept发生在三次握手哪个阶段?

accept发生在三次握手之后。

第一次握手:客户端发送syn包(syn=j)到服务器。

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个ASK包(ask=k)。

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1)。

三次握手完成后,客户端和服务器就建立了tcp连接。这时可以调用accept函数获得此连接。

其他

如何使用ContentProvider进行批量操作?

通常进行数据的批量操作我们都会使用“事务”,但是ContentProvider如何进行批量操作呢?创建ContentProviderOperation对象数组,然后使用ContentResolver.applyBatch()将其分派给内容提供程序。您需将内容提供程序的授权传递给此方法,而不是特定内容URI。这样可使数组中的每个ContentProviderOperation对象都能适用于其他表。调用ContentResolver.applyBatch()会返回结果数组。

同时我们还可以通过ContentObserver对数据进行观察:

1. 创建我们特定的ContentObserver派生类,必须重载onChange()方法去处理回调后的功能实现

2. 利用context.getContentResolover()获得ContentResolove对象,接着调用registerContentObserver()方法去注册内容观察者,为指定的Uri注册一个ContentObserver派生类实例,当给定的Uri发生改变时,回调该实例对象去处理。

3. 由于ContentObserver的生命周期不同步于Activity和Service等,因此,在不需要时,需要手动的调用unregisterContentObserver()去取消注册。

常用的网络请求框架有哪些?

● Retrofit

● OkHttp

● NoHttp

● Volley

● HttpURLConnection(省电省流量)

● HttpClient(6.0后删除)

● AsyncHttpclient

请求头Map mHeaders,请求参数Map mBodyParams,URLEncoder.encode()

● NetworkExecutor 网络请求线程

● HttpStack Http执行器

● ResponseDelivery Response分发

每日一题:简单的说一下布局相关的 、 控件作用及实现原理

简单的说一下布局相关的 、 控件作用及实现原理

ViewStub本身是一个视图,会被添加到界面上,之所以看不到是因为其设置了隐藏与不绘制

当调用infalte或者ViewStub.setVisibilty(View.VISIBLE)时(两个都使用infalte逻辑),先从父视图上把当前ViewStub删除,再把加载的android:layout视图添加上

把ViewStub LayoutParams 添加到加载的android:layout视图上,而其根节点的LayoutParams设置无效

ViewStub是指用来占位的视图,通过删除自己并添加android:layout视图达到懒加载效果

每日一题:Framework 工作方式及原理,Activity 是如何生成一个 view 的,机制是什么?

参考答案:

所有的框架都是基于反射 和 配置文件(manifest)的。

普通的情况:

Activity 创建一个 view 是通过 ondraw 画出来的, 画这个 view 之前呢,还会调用 onmeasure 方法来计算显示的大小.

特殊情况:

Surfaceview 是直接操作硬件的, 因为 或者视频播放对帧数有要求,

onDraw 效率太低,不够使,Surfaceview 直接把数据写到显存。

Framework 是Android 系统对Linux kenel,lib库的封装,提供WMS,AMS,,Binder机制,handler-message 机制,提供APP使用

简单来说Framework就是提供app生存的环境

1)Activity 在 attach 方法的时候,汇创间一个photowindow(window子类)

2)onCreate中setContentView,会创建DectorView

3)DectorView 的 addView 方法,会把Layout中的布局加载进来

反射,配置文件

每个Activity里面都有Window.callback 和 keyevent.callback一些回调的接口或者函数,框架把Activity创建出来就会回调这些方法和Activity的声明周期方法

Activity 创建一个 view 是通过 ondraw 画出来的, 画这个 view 之前呢,还会调用 onmeasure 方法来计算显示的大小.

特殊情况:

Surfaceview 是直接操作硬件的, 因为 或者视频播放对帧数有要求,

onDraw 效率太低,不够使,Surfaceview 直接把数据写到显存。

每日一题:RelativeLayout和LinearLayout在实现效果同等的情况下使用哪个?为什么?

选择LinearLayout,因为RelativeLayout在measure过程需要两次

//RelativeLayout源码

View[] views = mSortedHorizontalChildren;

int count = views.length;

for (int i = 0; i < count; i++) {

/**/

measureChildHorizontal(child, params, myWidth, myHeight);

}

/**/

for (int i = 0; i < count; i++){

/***/

measureChild(child, params, myWidth, myHeight);

}

//LinearLayout

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

if (mOrientation == VERTICAL) {

measureVertical(widthMeasureSpec, heightMeasureSpec);

} else {

measureHorizontal(widthMeasureSpec, heightMeasureSpec);

}

}

从源码我们发现RelativeLayout会对子View做两次measure。这是为什么呢?首先RelativeLayout中子View的排列方式是基于彼此的依赖关系,而这个依赖关系可能和布局中View的顺序并不相同,在确定每个子View的位置的时候,就需要先给所有的子View排序一下。又因为RelativeLayout允许A B两个子View,横向上B依赖于A,纵向上A依赖于B,所以需要横向纵向分别进行一次排序测量。

RelativeLayout另外一个性能问题:

View的measure方法里对绘制过程做了一个优化,如果我们的子View没有要求强制刷新,而父View给子View的传入值也没有变化,也就说子View的位置没有变化,就不会做无谓的measure。但是上面已经说了RelativeLayout要做两次measure,而在做横向测量时,纵向的测量结果尚未完成,只好暂时使用myHeight传入子View系统,假如子View的Height不等于(设置了margin)myHeight的高度,那么measure中优化则不起作用,这一过程将进一步影响RelativeLayout的绘制性能。而LinearLayout则无这方面的担忧,解决这个问题也很好办,如果可以,尽量使用padding代替margin。

结论

RelativeLayout会让子View调用两次onMeasure,LinearLayout再有weight时,也会调用子View两次onMeasure

RelativeLayout的子View如果高度和RelativeLayout不同,则会引发效率问题。当子View很复杂时,这个问题会更加严重。如果可以,尽量使用padding代替margin

在不影响层级深度的情况下,使用LinaerLayout和FrameLayout而不是RelativeLayout

每日一题:Java 中堆和栈有什么不同?

参考答案:

为什么把这个问题归类在多线程和并发面试题里?因为栈是一块和线程紧密相关的内存区域。每个线程都有自己的栈内存,用于存储本地变量,方法参数和栈调用,一个线程中存储的变量对其它线程是不可见的。而堆是所有线程共享的一片公用内存区域。对象都在堆里创建,为了提升效率线程会从堆中弄一个缓存到自己的栈,如果多个线程使用该变量就可能引发问题,这时 volatile 变量就可以发挥作用了,它要求线程从主存中读取变量的值

每日一题:数据库的四大特征,数据库的隔离级别?

参考答案:

事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列, 这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。例如,银 行转账工作:从一个账号扣款并使另一个账号增款,这两个操作要么都执行,要 么都不执行。所以,应该把它们看成一个事务。事务是数据库维护数据一致性的 单位,在每个事务结束时,都能保持数据一致性。

事务具有以下 4 个基本特征:数据库的四大特征:

(1)原子性(Atomicity)

原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。

(2)一致性(Consistency)

一个事务执行之前和执行之后都必须处于一致性状态。

(3)隔离性(Isolation)

隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个 用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

(4)持久性(Durability)

持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性 的。

数据库的隔离级别:

1)Serializable(串行化):可避免脏读、不可重复读、幻读的发生。

2)Repeatable read (可重复读):可避免脏读、不可重复读的发生。

3)Read committed (读已提交):可避免脏读的发生。

4)Read uncommitted (读未提交):最低级别,任何情况都无法保证。

`每日一题:多进程场景遇见过么?

参考答案:

在新的进程中,启动前台 Service,播放音乐。

一个成熟的应用一定是多 模块化的。首先多进程开发能为应用解决了 OOM 问题,因为 Android 对内存的 限制是针对于进程的,所以,当我们需要加载大图之类的操作,可以在新的进程 中去执行,避免主进程 OOM。而且假如图片浏览进程打开了一个过大的图片, java heap 申请内存失败,该进程崩溃并不影响我主进程的使用。

每日一题:服务启动一般有几种,服务和 activty 之间怎么通信,服务和服务之间怎么通信

参考答案:

1、startService:onCreate()--->onStartCommand() ---> onDestory() 如果服务已经开启,不会重复的执行 onCreate(), 而是会调用 onStartCommand()。一旦服务开启跟调用者(开启者)就没有任何关系了。开启 者退出了,开启者挂了,服务还在后台长期的运行。开启者不能调用服务里面 的方法。

2、bindService:onCreate() --->onBind()--->onunbind()--->onDestory() bind 的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。绑定者可 以调用服务里面的方法。

3、通信:

通过 Binder 对象。

通过 broadcast(广播)。

每日一题:Handler、Thread 和 HandlerThread 的差别

参考答案:

Handler:在 android 中负责发送和处理消息,通过它可以实现其他支线线程 与主线程之间的消息通讯。

Thread:Java 进程中执行运算的最小单位,亦即执行处理机调度的基本单位。某一进程中一路单独运行的程序。

HandlerThread:一个继承自 Thread 的类 HandlerThread,Android 中没有 对 Java 中的 Thread 进行任何封装,而是提供了一个继承自 Thread 的类 HandlerThread 类,这个类对 Java 的 Thread 做了很多便利的封装。HandlerThread 继承于 Thread,所以它本质就是个 Thread。与普通 Thread 的差 别就在于,它在内部直接实现了 Looper 的实现,这是 Handler 消息机制必不可 少的。有了自己的 looper,可以让我们在自己的线程中分发和处理消息。如果 不用 HandlerThread 的话,需要手动去调用 Looper.prepare()和 Looper.loop() 这些方法。

每日一题:Service生命周期

参考答案:

startService() --> onCreate() --> onStartCommand() --> Service running --> onDestory()

bindService() --> onCreate() --> onBind() --> Service running --> onUnbind() --> onDestory()

onCreate():

系统在Service第一次创建时执行此方法,来执行只运行一次的初始化工作,如果service已经运行,这个方法不会调用。

onStartCommand():

每次客户端调用startService()方法启动该Service都会回调该方法(多次调用),一旦这个方法执行,service就启动并且在后台长期运行,通过调用stopSelf()或stopService()来停止服务。

onBind():

当组件调用bindService()想要绑定到service时,系统调用此方法(一次调用),一旦绑定后,下次在调用bindService()不会回调该方法。在你的实现中,你必须提供一个返回一个IBinder来使客户端能够使用它与service通讯,你必须总是实现这个方法,但是如果你不允许绑定,那么你应返回null

onUnbind():

当前组件调用unbindService(),想要解除与service的绑定时系统调用此方法(一次调用,一旦解除绑定后,下次再调用unbindService()会抛异常)

onDestory():

系统在service不在被使用并且要销毁的时候调用此方法(一次调用)。service应在此方法中释放资源,比如线程,已注册的监听器、接收器等等。

每日一题:你知道Android消息机制模型吗?

参考答案:

消息机制主要包含:MessageQueue、Handler、Looper和Message这四大部分。

Message:需要传递的消息,可以传递数据

MessageQueue:消息队列,但是它的内部实现并不是用的队列,实际上是通过一个单链表的数据结构来维护消息列表,因为单链表在插入和删除上比较有优势。主要功能是向消息池传递消息(MessageQueue.enqueueMessage)和取走消息池的消息(MessageQueue.next)

Handler:消息辅助类,主要功能是向消息池发送各种消息事件(Handler.sendMessage)和处理相应消息事件(Handler.handleMessage)

Looper:不断循环执行(Looper.loop),从MessageQueue中读取消息,按分发机制将消息分发给目标处理者。

每日一题:哪些情况下的对象会被垃圾回收机制处理掉?

参考答案:

所有实例都没有活动线程访问。

没有被其他任何实例访问的循环引用实例。

Java 中有不同的引用类型。判断实例是否符合垃圾收集的条件都依赖于它的引用类型。

要判断怎样的对象是没用的对象。这里有 2 种方法:

采用标记计数的方法:给内存中的对象给打上标记,对象被引用一次,计数就加 1,引用被释放了,计数就减一,当这个计数为 0 的时候,这个对象就可以被回收了。当然,这也就引发了一个问题:循环引用的对象是无法被识别出来并且被回收的。所以就有了第二种方法:

采用根搜索算法:从一个根出发,搜索所有的可达对象,这样剩下的那些对象就是需要被回收的

Java

Java 中 static 关键字是什么意思?

static是Java里的非访问修饰符,它可以用来创建类方法和类变量。

当修饰一个变量的时候,此变量就成了独立于对象的静态变量,无论一个类实例化了多少个对象,这个类只有一份这个静态变量的拷贝,所以static修饰的变量,即静态变量,也被叫做类变量。一个局部变量不能被声明为static变量。

当修饰一个方法的时候,此方法就成了独立于对象的静态方法,静态方法不能使用类的非静态变量,因为静态方法和静态变量先于非静态的其他成员初始化,静态方法先出来,然后才是非静态的,所以明白这个顺序很重要。静态方法从参数列表得到数据,然后计算这些数据。

有些人认为static方法不是面向对象的,因为它们确实具有全局函数的语义;使用static方法时,由于不存在this,所以不是通过「向对象发送消息」的方式来完成的。当代码中出现很多static方法时,你应该反思自己的设计的,然而,static确有其用。

总结一下,当static:

修饰方法时,此方法能够不用在初始化对象的前提下直接调用,即,可以直接通过类名.static方法()这样来访问。

修饰代码块时,这部分代码块只会被执行一次。

修饰变量时,这个变量只在内存中有一个副本。

这个 结果如何解释

Integer a = 100,b=100;

Integer c = 1000,d= 1000;

System.out.println(a==b);

System.out.println(c==d);

输出: true,false

原因,Intenger 赋值的时候用的是Integer.valueOf(x)

在int -128·127 有个高速的缓存,如果在此期间直接给缓存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值