前语
面试专题前面的百度篇,腾讯篇,阿里篇,京东篇,bilibili篇,网易篇,字节篇,小红书,小米九大板块已经更新完了,还剩下2个专题~持续更新中。
1.12W字;2022最新Android11位大厂面试专题(一)百度篇
2.12W字;2022最新Android11位大厂面试专题(二)阿里篇
3.12W字;2022最新Android11位大厂面试专题(三)腾讯篇
4.面霸养成记;50万字Android面试文档(四五)字节,京东篇
5.面霸养成记;50万字Android面试文档(六七)网易,Bilibili篇
6.面霸养成记;50万字Android面试文档(八九)小红书,小米篇
一共50W字的文档,面试专题12W字仅仅一小部分,字数约束,分几篇更。
重视公众号:Android苦做舟
提前解锁 《整套50W字Android系统PDF》,让学习更靠近未来实战。
总共包括:
1.腾讯Android开发笔记(33W字)
2.2022最新Android十一位大厂面试专题(12W字)
3.音视频经典面试题(6W字)
4.Jetpack全家桶
5.Android 功能监控框架Matrix
6.JVM
7.车载使用开发
共十一模块,今日来更新第八丶九专题小米篇和小红书篇
八丶小米
1.handler机制
(第二章第3题)
2.一个线程中几个handler一起发送一个相同的音讯,怎样分辨哪个音讯是哪个handler发送的
(每个msg都有对应的target
,这个target
其实便是对应handler的引证。所以是经过msg.target
区分的 )
3.Android服务的生命周期
服务生命周期具有以下回调
-
onCreate()
:
在首次创建服务以设置您可能需求的初始配置时履行。仅在服务没有运转时才履行此办法。
-
onStartCommand()
:
每次履行startService()
都由另一个组件(例如Activity或BroadcastReceiver)调用。运用此办法时,服务将一向运转,直到您调用stopSelf()
或中止stopService()
。请注意,无论您调用多少次onStartCommand()
,办法stopSelf()
和都stopService()
有必要仅被调用一次才干中止服务。
-
onBind()
:
在组件调用bindService()
并返回IBInder的实例时履行,以供给与Service的通讯通道。bindService()
只要有绑定到它的客户端,对的调用将使服务保持运转。
-
onDestroy()
:
在不再运用该服务并允许处置已分配的资源时履行。
请必须注意,在服务的生命周期中可能会调用其他回调,例如onConfigurationChanged()andonLowMemory()
4.Android持久化存储的办法
内部存储、网络存储、SharedPreferences、SQLite、外部存储(SD卡)。
5.Android播送运用
动态注册播送:
在MainActivity
中:
public class MainActivity extends AppCompatActivity {
private MyReceiver myReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn1 = findViewById(R.id.btn);
myReceiver = new MyReceiver();
registerReceiver(myReceiver,new IntentFilter("wk")); //IntentFilter的参数为播送承受的类型(自界说)
btn1.setOnClickListener((v)-> sendBroadcast(new Intent("wk"))); //Intent的参数为发送播送的类型(自界说)
}
class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "我是动态注册的播送", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(myReceiver); //Activity销毁时反注册,避免内存走漏
}
}
点击按钮后在MainActivity
中发送播送,MyReceiver就能承受到播送Toast:
静态注册播送:
直接在包名按右键新建一个:
新建完要在Manifest界说这个播送接纳什么类型:
<application
.....
<receiver
android:name=".MyReceiver2"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="wk"/> //界说播送接纳的类型(自界说)
</intent-filter>
</receiver>
.....
</application>
发送播送时界说好发送的类型就能接纳到播送了
6.自界说view哪个结构办法是不能不重写的
在setContentView
源码能够看到普通view的创建办法是createViewFromTag
。找到view = createView(context, name, null, attrs);
点进去看到根节点的view是经过反射获取的,然后获取根节点的结构办法clazz.getConstructor(mConstructorSignature) mConstructorSignature
是两个参数的数组。所以自界说View一定要重写两个参数的结构函数
/**
* Creates a view from a tag name using the supplied attribute set.
* <p>
* <strong>Note:</strong> Default visibility so the BridgeInflater can
* override it.
*
* @param parent the parent view, used to inflate layout params
* @param name the name of the XML tag used to define the view
* @param context the inflation context for the view, typically the
* {@code parent} or base layout inflater context
* @param attrs the attribute set for the XML tag used to define the view
* @param ignoreThemeAttr {@code true} to ignore the {@code android:theme}
* attribute (if set) for the view being inflated,
* {@code false} otherwise
*/
@UnsupportedAppUsage
View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
boolean ignoreThemeAttr) {
if (name.equals("view")) {
name = attrs.getAttributeValue(null, "class");
}
// Apply a theme wrapper, if allowed and one is specified.
if (!ignoreThemeAttr) {
final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
final int themeResId = ta.getResourceId(0, 0);
if (themeResId != 0) {
context = new ContextThemeWrapper(context, themeResId);
}
ta.recycle();
}
try {
View view = tryCreateView(parent, name, context, attrs);
if (view == null) {
final Object lastContext = mConstructorArgs[0];
mConstructorArgs[0] = context;
try {
if (-1 == name.indexOf('.')) {
view = onCreateView(context, parent, name, attrs);
} else {
view = createView(context, name, null, attrs);
}
} finally {
mConstructorArgs[0] = lastContext;
}
}
return view;
} catch (InflateException e) {
throw e;
} catch (ClassNotFoundException e) {
final InflateException ie = new InflateException(
getParserStateDescription(context, attrs)
+ ": Error inflating class " + name, e);
ie.setStackTrace(EMPTY_STACK_TRACE);
throw ie;
} catch (Exception e) {
final InflateException ie = new InflateException(
getParserStateDescription(context, attrs)
+ ": Error inflating class " + name, e);
ie.setStackTrace(EMPTY_STACK_TRACE);
throw ie;
}
}
/**
* Low-level function for instantiating a view by name. This attempts to
* instantiate a view class of the given <var>name</var> found in this
* LayoutInflater's ClassLoader.
*
* <p>
* There are two things that can happen in an error case: either the
* exception describing the error will be thrown, or a null will be
* returned. You must deal with both possibilities -- the former will happen
* the first time createView() is called for a class of a particular name,
* the latter every time there-after for that class name.
*
* @param viewContext The context used as the context parameter of the View constructor
* @param name The full name of the class to be instantiated.
* @param attrs The XML attributes supplied for this instance.
*
* @return View The newly instantiated view, or null.
*/
@Nullable
public final View createView(@NonNull Context viewContext, @NonNull String name,
@Nullable String prefix, @Nullable AttributeSet attrs)
throws ClassNotFoundException, InflateException {
Objects.requireNonNull(viewContext);
Objects.requireNonNull(name);
Constructor<? extends View> constructor = sConstructorMap.get(name);
if (constructor != null && !verifyClassLoader(constructor)) {
constructor = null;
sConstructorMap.remove(name);
}
Class<? extends View> clazz = null;
try {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, name);
if (constructor == null) {
// Class not found in the cache, see if it's real, and try to add it
clazz = Class.forName(prefix != null ? (prefix + name) : name, false,
mContext.getClassLoader()).asSubclass(View.class);
if (mFilter != null && clazz != null) {
boolean allowed = mFilter.onLoadClass(clazz);
if (!allowed) {
failNotAllowed(name, prefix, viewContext, attrs);
}
}
constructor = clazz.getConstructor(mConstructorSignature);
constructor.setAccessible(true);
sConstructorMap.put(name, constructor);
} else {
// If we have a filter, apply it to cached constructor
if (mFilter != null) {
// Have we seen this name before?
Boolean allowedState = mFilterMap.get(name);
if (allowedState == null) {
// New class -- remember whether it is allowed
clazz = Class.forName(prefix != null ? (prefix + name) : name, false,
mContext.getClassLoader()).asSubclass(View.class);
boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
mFilterMap.put(name, allowed);
if (!allowed) {
failNotAllowed(name, prefix, viewContext, attrs);
}
} else if (allowedState.equals(Boolean.FALSE)) {
failNotAllowed(name, prefix, viewContext, attrs);
}
}
}
Object lastContext = mConstructorArgs[0];
mConstructorArgs[0] = viewContext;
Object[] args = mConstructorArgs;
args[1] = attrs;
try {
final View view = constructor.newInstance(args);
if (view instanceof ViewStub) {
// Use the same context when inflating ViewStub later.
final ViewStub viewStub = (ViewStub) view;
viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
}
return view;
} finally {
mConstructorArgs[0] = lastContext;
}
} catch (NoSuchMethodException e) {
final InflateException ie = new InflateException(
getParserStateDescription(viewContext, attrs)
+ ": Error inflating class " + (prefix != null ? (prefix + name) : name), e);
ie.setStackTrace(EMPTY_STACK_TRACE);
throw ie;
} catch (ClassCastException e) {
// If loaded class is not a View subclass
final InflateException ie = new InflateException(
getParserStateDescription(viewContext, attrs)
+ ": Class is not a View " + (prefix != null ? (prefix + name) : name), e);
ie.setStackTrace(EMPTY_STACK_TRACE);
throw ie;
} catch (ClassNotFoundException e) {
// If loadClass fails, we should propagate the exception.
throw e;
} catch (Exception e) {
final InflateException ie = new InflateException(
getParserStateDescription(viewContext, attrs) + ": Error inflating class "
+ (clazz == null ? "<unknown>" : clazz.getName()), e);
ie.setStackTrace(EMPTY_STACK_TRACE);
throw ie;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
7.java怎样使得一个同步办法变为异步办法
结构一个异步调用
1.运用wait和notify办法
2.运用条件锁
3.Future
4.运用CountDownLatch
5.运用CyclicBarrier
8.java 笼统类和接口的差异
1、声明办法不同。笼统类为abstract class
,接口类为interface
。
2、承继笼统类关键字为extends
,完成接口关键字为implements
。
3、承继笼统类仅支撑单承继
,完成接口能够多完成
。
单承继:classB Extends classA 接口多完成:Interface implements Interface0, Interface1, interface2…… java中为什么要单承继,多完成? 若为多承继,那么当多个父类中有重复的特点或许办法时,子类的调用成果会含糊不清,因而用了单承继。 为什么能够多完成呢? 经过完成接口拓展了类的功能,若完成的多个接口中有重复的办法也不要紧,因为完成类中有必要重写接口中的办法,所以调用时还是调用的完成类中重写的办法。那么各个接口中重复的变量又是怎样回事呢?
4、笼统类能够有结构办法,接口中不能有结构办法。 5、笼统类能够有成员变量,接口类只能有常量(static)。 6、笼统类能够有成员办法,接口中只能够有笼统办法。 7、笼统类中添加办法能够影响子类,接口中添加办法通常影响子类(JDK1.8添加default办法不影响子类) 8、从JDK1.8开端允许接口中呈现非笼统办法,但需求default关键字修饰
- 主要减少了代码牵一发而动全身的弊端.
9.笼统类的办法一定要承继吗
当父类的笼统类中有笼统办法时,承继的子类有两种挑选,榜首:界说子类是笼统类,就不需求完成笼统办法;第二:完成所有的笼统办法,不需求界说子类为笼统类;
当父类的笼统类中没有笼统办法时,子类直接承继不用做任何操作。
九丶小红书
1.Java深仿制和浅仿制的差异
关于深仿制和浅仿制差异
- 浅仿制:浅仿制会在堆上创建一个新的方针(差异于引证仿制的一点),不过,假如原方针内部的特点是引证类型的话,浅仿制会直接仿制内部方针的引证地址,也便是说仿制方针和原方针共用同一个内部方针。
- 深仿制 :深仿制会完全仿制整个方针,包括这个方针所包含的内部方针。
2.自界说View是怎样绘制的?ViewGroup呢
(榜首章第2题)
3.Handler机制
(第二章第3题)
4.TCP和UDP的差异
①衔接
- TCP 是面向衔接的传输层协议,传输数据前先要树立衔接。
- UDP 是不需求衔接,即刻传输数据。
②服务方针
- TCP 是1对1的两点服务,即一条衔接只要两个端点。
- UDP 支撑1对1、一对多、多对多的交互通讯
③牢靠性
- TCP 是牢靠交给数据的,数据能够无差错、不丢掉、不重复、按需到达。
- UDP 是尽最大努力交给,不确保牢靠交给数据。
④拥塞操控、流量操控
- TCP 有拥塞操控和流量操控机制,确保数据传输的安全性。
- UDP 则没有,即便网络非常拥堵了,也不会影响 UDP 的发送速率。
⑤首部开支
- TCP 首部长度较长,会有一定的开支,首部在没有运用「选项」字段时是
20
个字节,假如运用了「选项」字段则会变长的。 - UDP 首部只要 8 个字节,并且是固定不变的,开支较小。
⑥传输办法
- TCP 是流式传输,没有鸿沟,但确保次序和牢靠。
- UDP 是一个包一个包的发送,是有鸿沟的,但可能会丢包和乱序。
⑦分片不同
- TCP 的数据巨细假如大于 MSS 巨细,则会在传输层进行分片,方针主机收到后,也同样在传输层组装 TCP 数据包,假如中途丢掉了一个分片,只需求传输丢掉的这个分片。
- UDP 的数据巨细假如大于 MTU 巨细,则会在 IP 层进行分片,方针主机收到后,在 IP 层组装完数据,接着再传给传输层。
TCP 和 UDP 使用场景:
因为 TCP 是面向衔接,能确保数据的牢靠性交给,因而常常用于:
-
FTP
文件传输; - HTTP / HTTPS;
因为 UDP 面向无衔接,它能够随时发送数据,再加上UDP本身的处理既简单又高效,因而常常用于:
- 包总量较少的通讯,如
DNS
、SNMP
等; - 视频、音频等多媒体通讯;
- 播送通讯;
一共50W字的文档,面试专题12W字仅仅一小部分,字数约束,分几篇更。
重视公众号:Android苦做舟
提前解锁 《整套50W字Android系统PDF》,让学习更靠近未来实战。
总共包括:
1.腾讯Android开发笔记(33W字)
2.2022最新Android十一位大厂面试专题(12W字)
3.音视频经典面试题(6W字)
4.Jetpack全家桶
5.Android 功能监控框架Matrix
6.JVM
7.车载使用开发