[{"content":"弄清楚Android的网络请求，OkHttp与Retrofit的区别与使用 目前主流的Android网络请求框架有OkHttp和Retrofit，不过Retrofit是对网络请求数据的封装，实际网络请求还是OkHttp进行，Retrofit其自身是不具备网络请求能力的。\n1.OkHttp的概念 OkHttp它代替了HttpUrlConnection和Apache的HttpClient（用于发送和接收HTTP请求的客户端编程工具包）\n\u0026mdash;默认情况下OkHttp具有以下的特性：\n·支持HTTP/2.0,HTTP/2.0是持久化连接，支持多路复用（客户端和服务端只有一个连接，通过一个连接可以发出多重请求）；\n·连接池减少请求延时（连接池就是通过复用预先创建好的连接，减少系统在连接建立与销毁上的开销，从而提升程序性能和稳定性的技术）；\n·透明的GZIP压缩下载大小（GZIP是网络传输中的“真空压缩技术”，它可以通过在服务器端压缩数据，在客户端自动解压，来大幅减小在数据传输量，从而让网络加载更快、更省流量）；\n·缓存相应内容，避免一些完全重复的网络请求；\n·网络出现问题之后，OkHttp能自动中恢复，如果服务器有多个IP地址，一个失败后，OKHttp会自动尝试连接其他的地址；\n2.OkHttp的使用流程 在使用OkHttp进行请求时，首先要创建一个OkHttpClient的实例\n1 val client = OkHttpClient() 如果想要发起一条Http请求，就需要创建一个Request对象\n1 val request = Request.Builder().url(url).build() 之后调用OkHttpClient的newCall方法来创建一个Call对象，并调用它的execute/enqueue方法来发送请求并获取服务器返回的数据（execute()方法是同步方法，enqueue()方法是异步方法）：\n1 val response = client.newCall(request).execute() response对象就是服务器返回的数据，可以使用下面的方法来得到返回的具体内容：\n1 val responseData = response.body?.string() 其OkHttp的基本请求流程就是创建OkHttpClient()、Request()、Call(),接着调用OkHttpClient()的newCall().execute()/enqueue()来请求数据并获取数据\n欢迎访问我的博客\n","date":"2026-03-03T00:00:00Z","image":"/p/android%E7%9A%84%E7%BD%91%E7%BB%9C%E8%AF%B7%E6%B1%82/cover.jpg","permalink":"/p/android%E7%9A%84%E7%BD%91%E7%BB%9C%E8%AF%B7%E6%B1%82/","title":"Android的网络请求"},{"content":"Handler学习 在Android开发中，消息传递和线程通信是常见的需求。而Android的Handler机制就是用来实现这种消息传递和线程通信的重要组件。它在Android应用开发中扮演者至关重要的角色。\n1.Handler组件 Handler的重要性： 1.线程间通信：Android应用通常会涉及到多个线程的并发执行，而Handler机制提供了一种简单而高效的方式来实现线程间的通信。通过Handler，我们可以将信息发送到目标线程的消息队列中，并在目标线程中处理消息，从而实现线程间的通信和合作。\n2.异步消息处理：在Android开发中，许多任务需要在后台线程中执行，完成后将结果更新到UI界面上。Handler机制允许我们在后台线程中处理任务，并通过Handler将结果发送到UI线程，以便更新UI界面。这种异步消息处理的机制在保持UI的响应性和避免阻塞主线程方面起到了至关重要的作用。\n3.定时任务处理：Handler机制还可以用于处理定时任务。我们可以使用Handler的postDelayed()方法来延迟代码块或发送延时消息。这对于实现定时刷新、定时执行任务等场景非常有用。\nHandler应用场景： 1.UI更新：当后台任务完成之后，通过Handler机制将结果发送到UI线程，以更新UI界面，如显示加载完成的数据，更新进度条等。\n2.后台任务处理：通过Handler机制，可以将后台任务发送到子线程来处理，避免主线程阻塞，从而保持UI的流畅性，如网络请求、文件读写等。\n3.定时任务：通过Handler的定时任务功能，可以实现定时执行代码块或延时发送消息，如定时刷新、定时通知等。\n4.线程间通信：通过Handler机制，在不同线程间发送消息和处理消息，实现线程间的通信和协作，如主线和后台线程之间的通信。\n2.Handler机制概述 Handler、Message和Looper的基本概念 Handler\nHandler是Android中的消息处理器，它负责接收和处理消息。每个Handler实例都关联一个特定的线程，并与该线程的消息队列相关联。通过Handler，我们可以发送和处理消息，实现线程间的通信和协作。\nMessage\nMessage是Handler传递的消息对象，用于在不同线程之间传递数据。它包含了要传递的数据和附加信息，如消息类型、标志等。Message对象可以通过Handler的sendMessage()方法发送到目标线程的消息队列中，并在目标队列中被处理。\nLooper\nLooper是一个消息循环器，它用于管理线程的消息队列。每个线程只能有一个Looper对象，它负责循环读取消息队列中的消息，并将消息传递给对应的Handler进行处理。Looper的工作方式是不断从消息队列中取出消息，并通过handler的dispatchMessage()方法将消息分发给目标Handler进行处理。\n工作原理:\n·当一个线程需要使用Handler来处理消息时，首先要先创建一个looper对象，并调用其prepare()方法创建一个与当前线程关联的消息队列。 ·接着，通过Looper的loop()方法启动消息循环，开始循环读取消息队列中的消息。 ·当有消息通过Handler的sendMessage()方法发送到消息队列时，Looper会不断从消息队列中取出消息，并将其传递给对应的Handler处理。 ·Handler在接收消息后，会调用自己的handleMessage()方法来处理消息。 源码结构 1.Handler的源码结构： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class Handler { private Looper mLooper; private MessageQueue mQueue; public Handler() { this(Looper.myLooper()); } public Handler(Looper looper) { mLooper = looper; mQueue = looper.getQueue(); } public void handleMessage(Message msg) { // 处理消息的逻辑 } public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (msg.target == null) { msg.target = this; } return mQueue.enqueueMessage(msg, delayMillis); } } 2.Message的源码结构 1 2 3 4 5 6 7 8 9 10 public final class Message { public int what; public Object obj; public Handler target; // 其他成员变量 public static Message obtain() { return new Message(); } } 3.Looper的源码结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public final class Looper { static final ThreadLocal\u0026lt;Looper\u0026gt; sThreadLocal = new ThreadLocal\u0026lt;\u0026gt;(); MessageQueue mQueue; private Looper() { mQueue = new MessageQueue(); } public static void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException(\u0026#34;Only one Looper may be created per thread\u0026#34;); } sThreadLocal.set(new Looper()); } public static Looper myLooper() { return sThreadLocal.get(); } public static void loop() { Looper me = myLooper(); if (me == null) { throw new RuntimeException(\u0026#34;No Looper; Looper.prepare() wasn\u0026#39;t called on this thread.\u0026#34;); } MessageQueue queue = me.mQueue; while (true) { Message msg = queue.next(); if (msg == null) { return; } msg.target.dispatchMessage(msg); msg.recycle(); } } public MessageQueue getQueue() { return mQueue; } } 4.关系和协作机制 ·Handler类通过持有Looper对象和与之关联的MessageQueue实现了消息的发送和处理。 ·Looper负责管理线程的消息循环，它在loop()方法中不断从MessageQueue中取出消息，并通过Handler的dispatchMessage()方法将消息分发给对应的Handler进行处理。 ·Message对象封装了要传递的消息和附加信息，包括目标Handler、消息类型等。 ·当调用Handler的sendMessage()或sendMessageDelayed()方法时，会将Message对象发送到MessageQueue中，等待Looper的循环读取和处理。 ·在Looper的循环过程中，取出的每个Message对象都会通过diapatchMessage()方法传递给目标Handler，最终由目标Handler的handleMessage()方法处理消息。 Handler的使用方法 1.创建Handler对象： 通过以下方式创建Handler对象：\n1 Handler handler = new handler(); 此时，Handler会与当前线程的Looper关联。\n2.发送消息： 使用Handler的sendMessage()或sendMessageDelayed()方法发送消息到消息队列中，供线程处理：\n1 2 3 4 Message msg = handler.obtainMessage(); msg.what = 1;//设置消息类型 msg.obj = \u0026#34;Hello\u0026#34;;//设置消息数据 handler.sendMessage(msg);//发送消息 上述代码创建了一个消息对象，设置了消息类型和数据，并通过Handler的sendMessage()方法将消息发送到消息队列中。\n3.处理消息： 在Handler中重写handleMessage()方法，用于处理接收到的消息：\n1 2 3 4 5 6 7 8 9 public void handleMessage(Message msg){ switch (msg.what) { case 1: String data = (String) msg.obj;//获取消息数据 //处理消息逻辑 break; //其他消息类型的处理 } } 在handleMessage()方法中，可以根据不同的消息类型进行逻辑处理。通过msg.obj可以获取消息携带的数据。\n4.在特定的线程中创建Handler对象 有时需要在特定的线程中创建Handler对象，可以通过Looper来实现。例如，在后台线程中创建Handler对象：\n1 2 3 4 5 6 7 8 9 10 11 12 13 Handler handler; Thread thread = new Thread(new Runnable() { public void run() { Looper.prepare(); handler = new Handler() { public void handleMessage(Message msg) { //处理消息逻辑 } }; Looper.loop(); } }); thread.start(); 通过在新的线程中调用Looper的prepare()和loop()方法，为该线程创建一个消息循环器，然后在该循环器中创建了Handler对象。这样，该Handler就与新线程的消息队列相关联，可以接收并处理该线程中的消息。\n5.Handler的线程安全性 1.创建Handler的正确方式：\n· 在主线程中创建Handler： 在主线程中创建Handler时，无需担心线程安全性问题，因为主线程默认具有一个消息循环器（即主线程的Looper）\n· 在其他线程中创建Handler： 在其他线程中创建Handler时，需要先调用Looper的prepare()和loop()方法来创建消息循环器，并确保在这个线程中只有一个Looper存在。\n2.处理消息的线程安全：\n· 避免直接访问UI元素： 如果Handler用于更新UI元素，确保只在主线程中更新UI。可以使用Handler的post()或postDelayed()方法将更新UI的任务提交到主线程执行。\n· 使用同步机制： 当多个线程同时访问Handler对象时，需要使用同步机制来保护共享资源，避免数据竞争和线程冲突。\n（1）·使用关键词synchronized： 在访问Handler的关键代码块或方法上使用synchronized关键字，以确保同一时间只有一个线程访问Handler对象。 （2）·使用线程安全的数据结构： 可以使用线程安全的数据结构，如ConcurrentLinkedQueue，来存储消息，以避免多个线程之间的竞争。\n3.确保消息的处理在正确的线程中执行：\n·发送到主线程的消息： 如果需要将消息发送到主线程处理，可以使用主线程的Handler，或者使用Activity或Fragment的runOnUiThread()方法。\n·发送到其他线程的消息： 如果需要将消息发送到其他线程处理，确保该线程拥有正确的Looper和消息循环器。可以使用Handler的构造函数或post()方法指定目标线程的Looper。\n总结\n为了确保Handler在多线程坏境下的线程安全性，需要注意以下几点：\n·在正确的线程中创建Handler对象。 ·在访问Handler对象时使用同步机制，如synchronized关键字。 ·避免直接访问UI元素，使用合适的方法更新UI。 ·确保消息的处理在正确的线程中执行，根据需要使用适当的Handler和Looper。 6.Handler的进阶操作 1.异步加载数据：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // 在后台线程中加载数据 Thread thread = new Thread(new Runnable() { public void run() { // 执行耗时操作，如网络请求或数据库查询 // 加载完成后，发送消息通知主线程 Message message = handler.obtainMessage(); message.what = LOAD_COMPLETE; message.obj = loadedData; handler.sendMessage(message); } }); thread.start(); // 主线程中处理消息 Handler handler = new Handler() { public void handleMessage(Message msg) { if (msg.what == LOAD_COMPLETE) { // 处理加载完成的数据 Object data = msg.obj; // 更新UI等操作 } } }; 2.延时操作：\n1 2 3 4 5 6 7 Handler handler = new Handler(); handler.postDelayed(new Runnable() { public void run() { // 延时操作，例如延时2秒后执行某个任务 // 更新UI等操作 } }, 2000); // 2000毫秒的延时 3.UI线程更新:\n1 2 3 4 5 6 7 Handler handler = new Handler(); handler.post(new Runnable() { public void run() { // 在UI线程中执行任务，用于更新UI // 更新UI等操作 } }); ","date":"2026-03-24T12:27:05Z","permalink":"/p/handler/","title":"Handler"},{"content":"Android四大组件学习 Android的四大组件包括：Activity（活动）、Service（服务）、BroadcaseReceiver（广播接收器）、ContentProvider（内容提供者）。\nActivity：通俗来讲其实就是App上面用户看到的每个界面，Activity组件负责界面展示、处理用户交互、进行数据传递等 Service：无界面的后台组件，用于执行长期执行的操作。就比如说应用商城后台下载的东西、后台播放网易云音乐等 BroadcaseReceiver：手机里的“消息喇叭”，用于监听系统或者应用发出的全局事件的组件，比如说网络状态的变化，充电状态的变化等 ContentProvider：应用间的“数据共享存储桥”，是管理跨应用访问的组件，通过URL来标识数据，比如说我们的手机通讯录是不是可以被多个应用访问读取 Activity(活动) 1.什么是Activity Activity通俗来讲就是用户所看到每一个页面，是Android应用中用来展示用户界面的组件，我们可以通过它来进行应用程序的交互。\nActivity可以想象成手机的每一个“页面”。比如当你打开一个App时，你看到的第一个界面就是一个Activity，这时你点击某一个按钮跳转到另一个界面就是另一个Activity。每一个Activity都是一个独立的界面，负责用户的交互和展示内容。\n2.Activity的生命周期 Activity的生命周期包括以下几个关键方法：\n1.onCreate(): Activity被创建调用。比如，当你点击QQ时，系统会创建QQ的MainActivity，并且调用OnCreate()这个方法。通常会在这里初始化界面和变量，这时候我们看到的界面是空白的。\n2.onStart()：Activity即将可见时调用。比如，QQ的首页即将显示在屏幕上。\n3.onResume()：Activity获得焦点，用户可以与之交互调用。比如，QQ可以完全显示出来，用户可以点击各种按钮来进行操作。\n4.onPuase(): Activity失去焦点时调用。比如，用户按了Home键回到桌面或者跳转到了另外一个界面。\n5.onStop()：Activity不再可见时调用，比如，你点击文章详情页进入到了文章里面。QQ的首页面被完全覆盖。\n6.onRestart()：Activity从停止状态重新启动时调用。首页Activity从后台回到前台。\n7.onDestory()：Activity被销毁时调用。比如，用户关闭了页面。\n简单来说，将Activity的生命周期来比作人的一生，那么：\n1.oncreate()：婴儿在母亲的肚子里，这时候别人还看不到婴儿，但是婴儿已经开始被初始化了\n2.onStart()：出生了，睁开眼，别人看可以看见我们了。但是我们还不会说话，不可以互动(也就是用户还不能跟界面进行互动)\n3.onResume()：我们长大了，步入青年，开始学习工作跟社会接触（用户可以跟界面进行交互）\n4.onPuase()：工作学习累了歇一会（Activity被部分遮挡（比如弹出了一个对话框）没有被完全遮挡还可以看到一部分）\n5.onStop()：退休了（Activity被完全遮挡（比如说跳转到了另外一个Activity上）不再显示在屏幕上面）。\n6.onRestart()：你决定重新开始工作（Activity从后台回到前台，准备重新显示）\n7.onDestory()：生命的尽头，over掉了（Activity被系统销毁，释放资源）\n3.Activity的生命周期示例 Servive(服务) 1.什么是Service 可以把Service想象成一个“后台默默无闻的打工人”，它没有UI界面，默默的在后台干活，比如播放音乐、下载文件 、处理网络请求等。即使你退出了App，没有杀死后台，那么Service还可以继续运行。 简而言之，Service就是一个无界面的后台组件，用来执行需要长期运行的操作。\n2.Service的类型 Service有两种类型：\nStarted Service（启动式服务） 特点：通过startService()启动，会一直运行，直到任务完成或调用stopSelf()\n适用场景：执行一次性任务，比如下载文件、播放音乐\n生命周期：onCreate()-\u0026gt;onStartCommand()-\u0026gt;onDestroy()\nBound Service（绑定式服务） 特点：通过bindService()启动，允许多个组件（比如Activity）绑定到同一个Service。当所有组件解绑后，Service会被销毁\n适用场景：提供长期服务，比如后台计算、数据同步\n生命周期：onCreate()-\u0026gt;onBind()-\u0026gt;onUnbind()-\u0026gt;onDestroy()\n3.Service示例 BroadCaseReceiver（广播接收器） 1.什么是BroadCaseReceiver 可以把广播接收器想象成一个“收音机”，它的作用是监听系统或应用发出的“广播信息”，并在收到消息后执行相应的操作。\n比如： ·手机电量过低，系统检测到了，会发出一个“低电量“的广播，广播接收器可以接收到这个消息并提醒你充电。 ·你下载了一个App，下载完成之后，系统会发出一个“下载完成的广播，广播接收器接收到这个消息之后会提醒你进行安装。 简而言之，广播接收器就是用来接收和处理广播消息的组件。\n2.BroadCaseReceiver的类型 广播分为两种类型：\n（1）系统广播\n·特点：由系统发出，比如电池电量低、网络状态变化、屏幕开关等。 ·比如： ACTION_BATTERY_LOW:电池电量低。 ACTION_BOOT_COMPLETED:设备启动完成。 （2）自定义广播\n·特点：由应用发出，用于应用内部或应用之间的通信。 ·比如：在App定义一个广播，比如“任务完成”，然后在其他地方接收并处理。 3.BroadCaseReceiver的注册方式 广播接收器可以通过两种方式注册：\n1.静态注册 在AndroidManifest.xml里面声明，应用为运行时也能接收到广播。 适用场景：监听系统广播，比如设备启动完成。\n示例：\n1 2 3 4 5 \u0026lt;receiver android:name=\u0026#34;.MyReceiver\u0026#34;\u0026gt; \u0026lt;intent-filter\u0026gt; \u0026lt;action android:name=\u0026#34;android.intent.action.BOOT_COMPLETED\u0026#34; /\u0026gt; \u0026lt;/intent-filter\u0026gt; \u0026lt;/receiver\u0026gt; 2.动态注册 在代码中通过**registerReceiver()**注册，通常用于应用运行时的广播。 适用场景：监听应用内部的广播，比如用户点击按钮后发出的广播（例如点击播放下一首音乐的按钮，播放界面接收到发出的广播后就会更新界面UI）\n示例：\n1 2 IntentFilter filter = new IntentFilter(\u0026#34;com.example.MY_CUSTOM_ACTION\u0026#34;); registerReceiver(myReceiver, filter); 4.BroadCaseReceiver的生命周期 广播接收器的生命周期很简单，主要包括两个阶段：\n1.*接收广播：当广播发出时，系统会创建广播接收器的实例，并调用它的onReceive()方法。 2.*完成任务：onReceive()方法执行完毕之后，广播接收器的实例会被销毁。 也就是说，广播接收器的生命周期很短暂，它只存在于接收广播并处理完广播的这段时间内。\n5.BroadCaseReceiver的工作流程 BroadCaseReceiver的核心类是android.content.BroadCaseReceiver,一个抽象类\n广播接收器的工作流程\n（1）注册广播接收器 ·静态注册：由PackgeManagerService解析AndroidManifest.xml并注册。 ·动态注册：通过Content.registerReceiver()注册到ActivityManagerService。 （2）发送广播 ·通过Content.sendBroadcase()发送广播，ActivityManagerService负责分发。 （3）分发广播 ·BroadcaseQueue从队列中取出广播，并调用广播接收器的onReceive()方法处理。 （4）处理广播 ·广播接收器的onReceive()方法在运行在主线程中，不能执行耗时操作。 总而言之：BroadcastReceiver工作流程是：PMS/AMS管理注册 → AMS接收广播并匹配 → BroadcastQueue按类型分发 → 应用主线程执行onReceive（10秒内必须返回）→ 整个过程通过Binder IPC跨进程通信，系统通过超时机制防止接收器阻塞主线程。\nContentProvider(内容提供者) 1.什么是ContentProvider 访问方（其他应用）不需要知道数据是存储在SQLite数据库、文件系统还是网络上，只需要通过ContentResolver（内容解析器）对象，传入对应的URL和参数，即可以完成操作。ContentResolver会负责找到正确的ContentProvider并执行请求。\n简而言之：contentProcvider其实就是应用间的“数据共享桥”，是管理跨应用访问的组件，通过URL来表示数据。\n比如： 手机里面的通讯录，存储了许多人的信息，你如果想把这些联系人分享给其他App，就可以通过ContentProvider来实现。\n总结就是：ContentProvider就是用来共享和管理数据的组件。\n2.ContentProvider的特点 1.⭐数据共享：ContentProvider可以让不同应用之间共享数据。比如，通讯录App可以通过ContentProvider分享给别人（将联系人信息共享给其他App）。 2.⭐统一接口：ContentProvider提供了一套标准化接口（比如query()、insert()、update()、delete()），其他应用可以通过这些接口来访问数据。 3.⭐数据安全：ContentProvider可以通过权限控制来保护数据。比如：你可以设置只有特定的应用才能访问你的数据。 3.ContentProvider的核心方法 ContentProvider的核心方法包括：\n1.query():查询数据。 2.insert():插入数据。 3.update():更新数据。 4.delete():删除数据。 5.getType():返回数据的MIME类型。 总结 Android的四大模块分工明确：\n1.Activity（活动）：负责界面的展示与应用之间的交互，负责展示界面，用户可以通过界面来与应用进行交互，也就是App的一个个“页面”。\n2.Service（服务）：在后台默默打工的打工人，比如说下载应用或者播放音乐等会在后台挂着，直到任务完成或者执行stopSelf(),没有界面但能够长期运行。\n3.BroadCaseReceiver（广播接收者）：像“收音机”一样接收系统或者应用发出的广播，比如电量低或者下载完成的广播，接收到之后会做出响应。\n4.ContentProvider（内容提供者）：是用来跨应用共享数据的“数据管家”，管理应用的数据并提供统一的接口，让其他应用也可以访问到这些数据。\n总而言之：Activity管界面，Service管后台，BroadCaseReceiver管消息，ContentProvider管数据。\n","date":"2026-03-14T10:04:26Z","permalink":"/p/android-module/","title":"Android Module"},{"content":"LeedCode 1.两数相加 1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution { public: vector\u0026lt;int\u0026gt; twoSum(vector\u0026lt;int\u0026gt;\u0026amp; nums, int target) { map\u0026lt;int,int\u0026gt; m; for(int i=0;i\u0026lt;nums.size();i++){ if(m.count(target-nums[i])==0){//count的作用是返回键出现的次数为0则是没有找到差值，为1则是找到差值 m.insert({nums[i],i});//如果没有找到则插入数据，（）是函数调用，用{}构造 } else return {m[target-nums[i]],i};//如果找到差值则返回，m[target-nums[i]]的意思是返回该键值的下标 } return {};//否则则返回空 } }; ","date":"2026-03-13T08:11:52Z","permalink":"/p/leetcode%E5%90%88%E9%9B%86/","title":"LeetCode合集"},{"content":"学习retrofit的使用过程 Retrofit的简介 准确的来说，Retrofit是一个RESTful的HTTP网络请求框架的封装，实际网络请求工作的本质是由OkHttp完成，Retrofit仅负责网络请求接口的封装（Retofit接口层封装请求参数、Header、URL等） 在服务器返回响应数据的时候，OkHttp将原始的结果返回给Retrofit，Retrofit会根据用户的需求对返回数据进行解析\nRetrofit 使用步骤 step1:添加Retrofit库的依赖\nstep2：创建接收服务器返回数据的类\nstep3：创建用于描述网络请求的接口\nstep4：创建Retrofit实例\n1 2 3 4 5 Retrofit retrofit = new Retrofit.Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create())//设置数据解析器 .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//支持RxJava平台 .build(); step5：创建网络请求接口实例并配置网络请求参数\nstep6:发送网络请求（同步/异步）\nstep7：处理服务器返回的数据\n","date":"2026-03-05T07:46:00Z","permalink":"/p/retrofit%E5%AD%A6%E4%B9%A0/","title":"Retrofit学习"},{"content":"弄清楚Android的网络请求，OkHttp与Retrofit的区别与使用 目前主流的Android网络请求框架有OkHttp和Retrofit，不过Retrofit是对网络请求数据的封装，实际网络请求还是OkHttp进行，Retrofit其自身是不具备网络请求能力的。\n1.OkHttp的概念 OkHttp它代替了HttpUrlConnection和Apache的HttpClient（用于发送和接收HTTP请求的客户端编程工具包）\n\u0026mdash;默认情况下OkHttp具有以下的特性：\n·支持HTTP/2.0,HTTP/2.0是持久化连接，支持多路复用（客户端和服务端只有一个连接，通过一个连接可以发出多重请求）；\n·连接池减少请求延时（连接池就是通过复用预先创建好的连接，减少系统在连接建立与销毁上的开销，从而提升程序性能和稳定性的技术）；\n·透明的GZIP压缩下载大小（GZIP是网络传输中的“真空压缩技术”，它可以通过在服务器端压缩数据，在客户端自动解压，来大幅减小在数据传输量，从而让网络加载更快、更省流量）；\n·缓存相应内容，避免一些完全重复的网络请求；\n·网络出现问题之后，OkHttp能自动中恢复，如果服务器有多个IP地址，一个失败后，OKHttp会自动尝试连接其他的地址；\n2.OkHttp的使用流程 在使用OkHttp进行请求时，首先要创建一个OkHttpClient的实例\n1 val client = OkHttpClient() 如果想要发起一条Http请求，就需要创建一个Request对象\n1 val request = Request.Builder().url(url).build() 之后调用OkHttpClient的newCall方法来创建一个Call对象，并调用它的execute/enqueue方法来发送请求并获取服务器返回的数据（execute()方法是同步方法，enqueue()方法是异步方法）：\n1 val response = client.newCall(request).execute() response对象就是服务器返回的数据，可以使用下面的方法来得到返回的具体内容：\n1 val responseData = response.body?.string() 其OkHttp的基本请求流程就是创建OkHttpClient()、Request()、Call(),接着调用OkHttpClient()的newCall().execute()/enqueue()来请求数据并获取数据\n","date":"2026-03-04T12:40:05Z","permalink":"/p/okhttp/","title":"OkHttp"},{"content":"This article offers a sample of basic Markdown syntax that can be used in Hugo content files, also it shows whether basic HTML elements are decorated with CSS in a Hugo theme.\nHeadings The following HTML \u0026lt;h1\u0026gt;—\u0026lt;h6\u0026gt; elements represent six levels of section headings. \u0026lt;h1\u0026gt; is the highest section level while \u0026lt;h6\u0026gt; is the lowest.\nH1 H2 H3 H4 H5 H6 Paragraph Xerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum, voluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma dolestendit peritin re plis aut quas inctum laceat est volestemque commosa as cus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin porecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur? Quiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit ut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda veliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore eost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata tiustia prat.\nItatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sapicia is sinveli squiatum, core et que aut hariosam ex eat.\nBlockquotes The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a footer or cite element, and optionally with in-line changes such as annotations and abbreviations.\nBlockquote without attribution Tiam, ad mint andaepu dandae nostion secatur sequo quae. Note that you can use Markdown syntax within a blockquote.\nBlockquote with attribution Don\u0026rsquo;t communicate by sharing memory, share memory by communicating.\n— Rob Pike1\nTables Tables aren\u0026rsquo;t part of the core Markdown spec, but Hugo supports supports them out-of-the-box.\nName Age Bob 27 Alice 23 Inline Markdown within tables Italics Bold Code italics bold code A B C D E F Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ultricies, sapien non euismod aliquam, dui ligula tincidunt odio, at accumsan nulla sapien eget ex. Proin eleifend dictum ipsum, non euismod ipsum pulvinar et. Vivamus sollicitudin, quam in pulvinar aliquam, metus elit pretium purus Proin sit amet velit nec enim imperdiet vehicula. Ut bibendum vestibulum quam, eu egestas turpis gravida nec Sed scelerisque nec turpis vel viverra. Vivamus vitae pretium sapien Code Blocks Code block with backticks 1 2 3 4 5 6 7 8 9 10 \u0026lt;!doctype html\u0026gt; \u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;utf-8\u0026#34;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Code block indented with four spaces \u0026lt;!doctype html\u0026gt; \u0026lt;html lang=\u0026quot;en\u0026quot;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026quot;utf-8\u0026quot;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Diff code block 1 2 3 4 5 [dependencies.bevy] git = \u0026#34;https://github.com/bevyengine/bevy\u0026#34; rev = \u0026#34;11f52b8c72fc3a568e8bb4a4cd1f3eb025ac2e13\u0026#34; - features = [\u0026#34;dynamic\u0026#34;] + features = [\u0026#34;jpeg\u0026#34;, \u0026#34;dynamic\u0026#34;] One line code block 1 \u0026lt;p\u0026gt;A paragraph\u0026lt;/p\u0026gt; List Types Ordered List First item Second item Third item Unordered List List item Another item And another item Nested list Fruit Apple Orange Banana Dairy Milk Cheese Other Elements — abbr, sub, sup, kbd, mark GIF is a bitmap image format.\nH2O\nXn + Yn = Zn\nPress CTRL + ALT + Delete to end the session.\nMost salamanders are nocturnal, and hunt for insects, worms, and other small creatures.\nThe above quote is excerpted from Rob Pike\u0026rsquo;s talk during Gopherfest, November 18, 2015.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"2023-09-07T00:00:00Z","permalink":"/p/markdown-syntax-guide/","title":"Markdown Syntax Guide"},{"content":"For more details, check out the documentation.\nBilibili video Tencent video YouTube video Generic video file Your browser doesn't support HTML5 video. Here is a link to the video instead. GitLab Quote Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n― A famous person, The book they wrote Photo by Codioful on Unsplash\n","date":"2023-08-25T00:00:00Z","image":"/p/shortcodes/cover.jpg","permalink":"/p/shortcodes/","title":"Shortcodes"}]