/** * A proxy setting that represents a {@code DIRECT} connection, * basically telling the protocol handler not to use any proxying. * Used, for instance, to create sockets bypassing any other global * proxy settings (like SOCKS): * <P> * {@code Socket s = new Socket(Proxy.NO_PROXY);} * */ publicfinalstaticProxyNO_PROXY=newProxy(); // Creates the proxy that represents a {@code DIRECT} connection. privateProxy() { type=Type.DIRECT; sa=null; }
publicenumType { /** * Represents a direct connection, or the absence of a proxy. */ DIRECT, /** * Represents proxy for high level protocols such as HTTP or http://FTP. */ HTTP, /** * Represents a SOCKS (V4 or V5) proxy. */ SOCKS };
应用层是网络应用程序和网络协议存放的分层,因特网的应用层包括许多协议,例如我们学 web 离不开的 HTTP,电子邮件传送协议 SMTP、端系统文件上传协议 FTP、还有为我们进行域名解析的 DNS 协议。应用层协议分布在多个端系统上,一个端系统应用程序与另外一个端系统应用程序交换信息分组,我们把位于应用层的信息分组称为 报文(message)。
因特网的网络层负责将称为 数据报(datagram) 的网络分层从一台主机移动到另一台主机。网络层一个非常重要的协议是 IP 协议,所有具有网络层的因特网组件都必须运行 IP 协议,IP 协议是一种网际协议,除了 IP 协议外,网络层还包括一些其他网际协议和路由选择协议,一般把网络层就称为 IP 层,由此可知 IP 协议的重要性。
链路层
现在我们有应用程序通信的协议,有了给应用程序提供运输的协议,还有了用于约定发送位置的 IP 协议,那么如何才能真正的发送数据呢?为了将分组从一个节点(主机或路由器)运输到另一个节点,网络层必须依靠链路层提供服务。链路层的例子包括以太网、WiFi 和电缆接入的 DOCSIS 协议,因为数据从源目的地传送通常需要经过几条链路,一个数据包可能被沿途不同的链路层协议处理,我们把链路层的分组称为 帧(frame)
浏览器正式的名字叫做 Web Broser,顾名思义,就是检索、查看互联网上网页资源的应用程序,名字里的 Web,实际上指的就是 World Wide Web,也就是万维网。
我们在地址栏输入URL(即网址),浏览器会向DNS(域名服务器,后面会说)提供网址,由它来完成 URL 到 IP 地址的映射。然后将请求你的请求提交给具体的服务器,在由服务器返回我们要的结果(以HTML编码格式返回给浏览器),浏览器执行HTML编码,将结果显示在浏览器的正文。这就是一个浏览器发起请求和接受响应的过程。
Web 服务器
Web 服务器的正式名称叫做 Web Server,Web 服务器一般指的是网站服务器,上面说到浏览器是 HTTP 请求的发起方,那么 Web 服务器就是 HTTP 请求的应答方,Web 服务器可以向浏览器等 Web 客户端提供文档,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。目前最主流的三个Web服务器是Apache、 Nginx 、IIS。
IP 协议的全称是 Internet Protocol 的缩写,它主要解决的是通信双方寻址的问题。IP 协议使用 IP 地址 来标识互联网上的每一台计算机,可以把 IP 地址想象成为你手机的电话号码,你要与他人通话必须先要知道他人的手机号码,计算机网络中信息交换必须先要知道对方的 IP 地址。(关于 TCP 和 IP 更多的讨论我们会在后面详解)
DNS
你有没有想过为什么你可以通过键入 http://www.google.com 就能够获取你想要的网站?我们上面说到,计算机网络中的每个端系统都有一个 IP 地址存在,而把 IP 地址转换为便于人类记忆的协议就是 DNS 协议。
DNS 的全称是域名系统(Domain Name System,缩写:DNS),它作为将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。
URI / URL
我们上面提到,你可以通过输入 http://www.google.com 地址来访问谷歌的官网,那么这个地址有什么规定吗?我怎么输都可以?AAA.BBB.CCC 是不是也行?当然不是的,你输入的地址格式必须要满足 URI 的规范。
GET 获取资源,GET 方法用来请求访问已被 URI 识别的资源。指定的资源经服务器端解析后返回响应内容。也就是说,如果请求的资源是文本,那就保持原样返回;
POST 传输实体,虽然 GET 方法也可以传输主体信息,但是便于区分,我们一般不用 GET 传输实体信息,反而使用 POST 传输实体信息,
PUT 传输文件,PUT 方法用来传输文件。就像 FTP 协议的文件上传一样,要求在请求报文的主体中包含文件内容,然后保存到请求 URI 指定的位置。
但是,鉴于 HTTP 的 PUT 方法自身不带验证机制,任何人都可以上传文件 , 存在安全性问题,因此一般的 W eb 网站不使用该方法。若配合 W eb 应用程序的验证机制,或架构设计采用REST(REpresentational State Transfer,表征状态转移)标准的同类 Web 网站,就可能会开放使用 PUT 方法。
HEAD 获得响应首部,HEAD 方法和 GET 方法一样,只是不返回报文主体部分。用于确认 URI 的有效性及资源更新的日期时间等。
DELETE 删除文件,DELETE 方法用来删除文件,是与 PUT 相反的方法。DELETE 方法按请求 URI 删除指定的资源。
OPTIONS 询问支持的方法,OPTIONS 方法用来查询针对请求 URI 指定的资源支持的方法。
Data inputData2 = new Data.Builder().putString("version", "1.0.0").build();
PeriodicWorkRequest checkVersionRequest =
new PeriodicWorkRequest.Builder(CheckVersionWork.class, 12, TimeUnit.HOURS)
.setInputData(inputData2).build();
public abstract void draw(@NonNull Canvas canvas,
CharSequence text,
@IntRange(from = 0) int start,
@IntRange(from = 0) int end,
float x,
int top,
int y,
int bottom,
@NonNull Paint paint);
public void draw(@NonNull Canvas canvas, CharSequence text,
@IntRange(from = 0) int start, @IntRange(from = 0) int end, float x,
int top, int y, int bottom, @NonNull Paint paint) {
public final int getByteCount() {
if (mRecycled) {
Log.w(TAG, "Called getByteCount() on a recycle()'d bitmap! "
+ "This is undefined behavior!");
return 0;
}
// int result permits bitmaps up to 46,340 x 46,340
return getRowBytes() * getHeight();
}
public final int getRowBytes() {
if (mRecycled) {
Log.w(TAG, "Called getRowBytes() on a recycle()'d bitmap! This is undefined behavior!");
}
return nativeRowBytes(mFinalizer.mNativeBitmap);
}
public static Bitmap decodeResource(Resources res, int id, Options opts) {
...
final TypedValue value = new TypedValue();
is = res.openRawResource(id, value);
bm = decodeResourceStream(res, value, is, null, opts);
...
}
public static Bitmap decodeResourceStream(Resources res, TypedValue value,InputStream is, Rect pad, Options opts) {
if (opts == null) {
opts = new Options();
}
if (opts.inDensity == 0 && value != null) {
final int density = value.density;
if (density == TypedValue.DENSITY_DEFAULT) {
opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
} else if (density != TypedValue.DENSITY_NONE) {
opts.inDensity = density;
}
}
if (opts.inTargetDensity == 0 && res != null) {
opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
}
fun hasFloatingWindowByView(activity: Activity): Boolean {
return getFloatWindowView(activity).isNotEmpty()
}
fun getFloatWindowByView(activity: Activity): List<View> {
// 对应步骤 2
val targetDecorView = activity.window.decorView
// 对应步骤 3
val acDecorViews = lifecycle.getActivities().map { it.window.decorView }.toList()
// 对应步骤 4
val mView = Window.getViews().map { it }.toList()
val targetIndex = mView.first { it == targetDecorView }
// 对应步骤 5
val index = mView.indexOf(targetIndex)
val floatView = arrayListOf<View>()
for (i in index + 1 until mView.size) {
if (acDecorViews.contains(mView[i])) {
break
}
floatView.add(mView[i])
}
return floatView
}
fun hasFloatWindowByToken(activity: Activity): Boolean {
// 获取目标 Activity 的 decorView
val targetDecorView = activity.window.decorView
// 获取目标 Activity 的 windowToken
val targetSubToken = targetDecorView.windowToken
// 拿到 mView 集合,找到目标 Activity 所在的 index 位置
val mView = Window.getViews().map { it }.toList()
val targetIndex = mView.indexOfFirst { it == targetDecorView }
// 获取 mParams 集合
val mParams = Window.getParams()
// 根据目标 index 从 mParams 集合中找到目标 token
val targetToken = mParams[targetIndex].token
class MyWallpaperService : WallpaperService() {
override fun onCreateEngine(): Engine = WallpaperEngine()
private inner class WallpaperEngine : WallpaperService.Engine() {
override fun onTouchEvent(event: MotionEvent?) {
// on finder press events
if (event?.action == MotionEvent.ACTION_DOWN) {
// get the canvas from the Engine or leave
val canvas = surfaceHolder?.lockCanvas() ?: return
// TODO
// update the surface
surfaceHolder.unlockCanvasAndPost(canvas)
}
}
}
}
//定义不可操作的一些行为
private const val DISABLE_BTN_1 = 1 shl 4
private const val DISABLE_BTN_2 = 1 shl 5
private const val DISABLE_BTN_3 = 1 shl 6
定义模式状态集,由状态+多个禁用标志位组成。 比如 MODE_A,就是在状态为 STATUS_A 的时候,按钮3禁用,那就将这两个数值进行或运算,结果就是 STATUS_A or DISABLE_BTN_3。
private const val MODE_A = STATUS_A or DISABLE_BTN_3
private const val MODE_B = STATUS_B or DISABLE_BTN_1 or DISABLE_BTN_3
private const val MODE_C = STATUS_C or DISABLE_BTN_2 or DISABLE_BTN_3
private val modeList = listOf(MODE_A, MODE_B, MODE_C)
从代码阅读性来说,使用这样的代码进行配置,看起来也比较通俗易懂。 比如 Pair(STATUS_A or DISABLE_BTN_3, "A3"),就是代表在状态A的时候,禁用按钮3,点击按钮的时候弹的Toast文案为 “A3”。
private val toastMap = hashMapOf(
Pair(STATUS_A or DISABLE_BTN_3, "A3"),
Pair(STATUS_B or DISABLE_BTN_1, "B1"),
Pair(STATUS_B or DISABLE_BTN_3, "B3"),
Pair(STATUS_C or DISABLE_BTN_2, "C2"),
Pair(STATUS_C or DISABLE_BTN_3, "C3")
)
/**
* 判断当前某个行为是否可操作
*
* @return true 可操作;false,不可操作。
*/
private fun checkEnable(action: Int): Boolean {
val result = modeList.filter {
(it and currentStatus) != 0
&& (it and action) != 0
}
if (result.isNotEmpty()) {
println("result is false, toast:${toastMap[currentStatus or action]}")
return false
}
println("result is true")
return true
}
复制代码
完整代码
object SixTeenTest {
//定义状态常量
private const val STATE_IDIE = 1
private const val STATUS_A = 1 shl 1
private const val STATUS_B = 1 shl 2
private const val STATUS_C = 1 shl 3
//定义不可操作的一些行为
private const val DISABLE_BTN_1 = 1 shl 4
private const val DISABLE_BTN_2 = 1 shl 5
private const val DISABLE_BTN_3 = 1 shl 6
//定义模式状态集
private const val MODE_A = STATUS_A or DISABLE_BTN_3
private const val MODE_B = STATUS_B or DISABLE_BTN_1 or DISABLE_BTN_3
private const val MODE_C = STATUS_C or DISABLE_BTN_2 or DISABLE_BTN_3
private val modeList = listOf(MODE_A, MODE_B, MODE_C)
//定义Toast映射关系
private val toastMap = hashMapOf(
Pair(STATUS_A or DISABLE_BTN_3, "A3"),
Pair(STATUS_B or DISABLE_BTN_1, "B1"),
Pair(STATUS_B or DISABLE_BTN_3, "B3"),
Pair(STATUS_C or DISABLE_BTN_2, "C2"),
Pair(STATUS_C or DISABLE_BTN_3, "C3")
)
//当前状态
private var currentStatus = STATE_IDIE
/**
* 判断当前某个行为是否可操作
*
* @return true 可操作;false,不可操作。
*/
private fun checkEnable(action: Int): Boolean {
val result = modeList.filter {
(it and currentStatus) != 0
&& (it and action) != 0
}
if (result.isNotEmpty()) {
println("result is false, toast:${toastMap[currentStatus or action]}")
return false
}
println("result is true")
return true
}
}
STATUS_A
result is true
result is true
result is false, toast:A3
STATUS_B
result is false, toast:B1
result is true
result is false, toast:B3
STATUS_C
result is true
result is false, toast:C2
result is false, toast:C3
@Suppress("UNCHECKED_CAST")
public override var value: T
// 拆箱
get() = NULL.unbox(_state.value)
// 更新数据
set(value) { updateState(null, value ?: NULL) }
// 拆箱操作
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
inline fun <T> unbox(value: Any?): T = if (value === this) null as T else value as T
@Suppress("UNCHECKED_CAST")
override fun resetReplayCache() {
throw UnsupportedOperationException("MutableStateFlow.resetReplayCache is not supported")
}
public static void quickSort(int[] arr,int start,int end){
//递归结束条件
if(start>=end){
return;
}
int standard = arr[start];//选取第start个元素为标准数
int low = start;//低位指针
int high = end;//高位指针
//通过一个循环将小的数字分配到标准数左边、
//大的放在右边,标准数放在中间
//循环的结束条件为两个指针碰撞即low==high,
while (low<high){
//首先从高位开始找比标准数小的数字
while (low<high&&standard<=arr[high]){
//将高位角标+1继续比较
high--;
}
//找到比标准数小的数字放在low角标处,此时的low即start
arr[low] = arr[high];
public class AnimalPlayground<T> {
public T create(Class<T> t) {
try {
return t.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding=ActivityMainBinding.inflate(LayoutInflater.from(this))
setContentView(binding.root)
val adapter=ItemTestListAdapter()
binding.rv.adapter=adapter
}
public void submitList(@Nullable final List<T> newList,
@Nullable final Runnable commitCallback) {
//...省略
//校验列表是否是同一个对象
if (newList == mList) {
// nothing to do (Note - still had to inc generation, since may have ongoing work)
if (commitCallback != null) {
commitCallback.run();
}
return;
}
//...省略
}
public class Order {
@SignField
private String sn;
@SignField
private String amt;
@SignField
private int status;
@SignField
private int userId;
@ValidField
private String sign;
}
下面就到了重头戏的部分,如何通过AOP来进行实现。
1. 定义切入点
@Pointcut("execution(@com.example.demo.annotations.Sign * *(..))")
public void signPointCut() {
}
@Pointcut("execution(@com.example.demo.annotations.Validate * *(..))")
public void validatePointCut() {
}
2.环绕切入点
@Around("signPointCut()")
public Object signAround(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
for (Object o : args) {
System.out.println(o);
sign(o);
}
Object res = pjp.proceed(args);
return res;
}
@Around("validatePointCut()")
public Object validateAround(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
Object res = pjp.proceed(args);
valid(res);
return res;
}
3. 签名的实现
1.获取需要签名字段
private Map<String, String> getSignMap(Object o) throws IllegalAccessException {
Map<String, String> fieldNameToValue = new HashMap<>();
for (Field f : o.getClass().getDeclaredFields()) {
System.out.println(f.getName());
for (Annotation annotation : f.getDeclaredAnnotations()) {
if (annotation.annotationType().equals(SignField.class)) {
String value = "";
f.setAccessible(true);
fieldNameToValue.put(f.getName(), f.get(o).toString());
}
}
}
return fieldNameToValue;
}
然后没有过多久,大约 10点半左右,开启了一个全员线上会议,会议全程 7 分钟左右。会议由 CEO David 主持,会议直接进入主题,这次 David 没有往昔的和颜悦色,全程只有 David,败家大佬 YC 并没有出现。之前这样的会议都是至少一个小时起步的,今天只有短短的几分钟,内容很简单,总结一句话就是:「我们将开启裁员行动」。
public synchronized void start() {
throw new IllegalThreadStateException();
group.add(this);
started = false;
try {
nativeCreate(this, stackSize, daemon);
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
最终调用的是一个jni方法
private native static void nativeCreate(Thread t, long stackSize, boolean daemon);
而nativeCreate最终在native层的实现是
static void Thread_nativeCreate(JNIEnv* env, jclass, jobject java_thread, jlong stack_size,
jboolean daemon) {
// There are sections in the zygote that forbid thread creation.
Runtime* runtime = Runtime::Current();
if (runtime->IsZygote() && runtime->IsZygoteNoThreadSection()) {
jclass internal_error = env->FindClass("java/lang/InternalError");
CHECK(internal_error != nullptr);
env->ThrowNew(internal_error, "Cannot create threads in zygote");
return;
}
// 这里就是真正的创建线程方法
Thread::CreateNativeThread(env, java_thread, stack_size, daemon == JNI_TRUE);
}
if (pthread_create_result == 0) {
// pthread_create started the new thread. The child is now responsible for managing the
// JNIEnvExt we created.
// Note: we can't check for tmp_jni_env == nullptr, as that would require synchronization
// between the threads.
child_jni_env_ext.release(); // NOLINT pthreads API.
return;
}
...
if (tlsPtr_.opeer != nullptr) {
ScopedObjectAccess soa(self);
// We may need to call user-supplied managed code, do this before final clean-up.
HandleUncaughtExceptions(soa);
RemoveFromThreadGroup(soa);
Runtime* runtime = Runtime::Current();
if (runtime != nullptr) {
runtime->GetRuntimeCallbacks()->ThreadDeath(self);
}
// Get and clear the exception.
ScopedLocalRef<jthrowable> exception(tlsPtr_.jni_env, tlsPtr_.jni_env->ExceptionOccurred());
tlsPtr_.jni_env->ExceptionClear();
public final void dispatchUncaughtException(Throwable e) {
// BEGIN Android-added: uncaughtExceptionPreHandler for use by platform.
Thread.UncaughtExceptionHandler initialUeh =
Thread.getUncaughtExceptionPreHandler();
if (initialUeh != null) {
try {
initialUeh.uncaughtException(this, e);
} catch (RuntimeException | Error ignored) {
// Throwables thrown by the initial handler are ignored
}
}
// END Android-added: uncaughtExceptionPreHandler for use by platform.
getUncaughtExceptionHandler().uncaughtException(this, e);
}
protected static final void commonInit() {
if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
/*
* set handlers; these apply to all threads in the VM. Apps can replace
* the default handler, but not the pre handler.
*/
LoggingHandler loggingHandler = new LoggingHandler();
RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler);
Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));
/*
* Install a time zone supplier that uses the Android persistent time zone system property.
*/
RuntimeHooks.setTimeZoneIdSupplier(() -> SystemProperties.get("persist.sys.timezone"));
LogManager.getLogManager().reset();
new AndroidConfig();
/*
* Sets the default HTTP User-Agent used by HttpURLConnection.
*/
String userAgent = getDefaultUserAgent();
System.setProperty("http.agent", userAgent);
/*
* Wire socket tagging to traffic stats.
*/
TrafficStats.attachSocketTagger();
// Don't re-enter -- avoid infinite loops if crash-reporting crashes.
if (mCrashing) return;
mCrashing = true;
if (ActivityThread.currentActivityThread() != null) {
ActivityThread.currentActivityThread().stopProfiling();
}
// Bring up crash dialog, wait for it to be dismissed
ActivityManager.getService().handleApplicationCrash(
mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
} catch (Throwable t2) {
if (t2 instanceof DeadObjectException) {
// System process is dead; ignore
} else {
try {
Clog_e(TAG, "Error reporting crash", t2);
} catch (Throwable t3) {
// Even Clog_e() fails! Oh well.
}
}
} finally {
// Try everything to make sure this process goes away.
Process.killProcess(Process.myPid());
System.exit(10);
}
}
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh)
方式,导入一个我们自定义的实现了UncaughtExceptionHandler接口的类
public interface UncaughtExceptionHandler {
/**
* Method invoked when the given thread terminates due to the
* given uncaught exception.
* <p>Any exception thrown by this method will be ignored by the
* Java Virtual Machine.
* @param t the thread
* @param e the exception
*/
void uncaughtException(Thread t, Throwable e);
}
publicThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler
)