自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(1078)
  • 收藏
  • 关注

原创 字节 1,2面 (Android)

了解哪些布局控件的layout,他们的区别“在实际项目中,我了解并使用过多种布局控件,这些控件各自有不同的特点和适用场景。常见的有LinearLayout、RelativeLayout(或者现今演变成的ConstraintLayout)、FrameLayout以及TableLayout。首先,LinearLayout是最简单的一种,它会按照水平方向或者垂直方向依次排列子控件。它的优点在于结构清晰、容易理解,但缺点是当界面比较复杂、需要灵活定位时就显得局限了,因为它只支持单一方向的排列。如果需要通过权重分配空

2025-05-18 20:00:35 449

原创 腾讯元宝 (Android)1,2面

除了以上传统加锁方式,还可以看到在某些场景中使用原子变量(如AtomicInteger、AtomicReference等)来替代加锁,利用底层的CAS(Compare-and-Swap)原理实现数据更新,这种方式更偏向于无锁编程,能够减少线程阻塞带来的开销。扩容过程中,不仅仅是简单的拷贝而已,而是会重新计算每个键对应的新位置,这是因为扩容后数组容量增加了,原来的散列算法需要重新映射才能保证数据分布均匀。这样一来,即使在碰撞较严重的情况下,一个桶内的操作性能也能保持在对数级别,从而避免了性能急剧下降的问题。

2025-05-17 20:13:13 696

原创 美图 (Android) 一面

讲讲自定义View属性在xml布局里面实现。讲讲synchronized。讲讲MVC和MVP的区别。Android启动方式。讲讲Kotlin协程。

2025-05-17 00:15:00 86

原创 美团客户端 -点评部 (Android) 一面

1.java泛型,泛型是怎么实现的,然后又问类型擦除2.重载和重写3.Java是如何进行内存回收的4.可达性算法5.线程池的应用场景,OkHttp中线程池有哪些参数6.OkHttp拦截器的设计模式7.MVVM设计模式8.MVVM架构,数据变化时如何通知UI刷新9.安卓中使用MVVM架构,会用到那些组件10.LiveData如何监听生命周期11.Glide的缓存机制12.Handler如何消费事件13.Handler只要处理哪些事件14.消息队列中有很多事件时,如何确保UI刷新事件的优先级15.有没有了解过其

2025-05-12 19:27:44 346

原创 针对面经 (Android)

实际上,在我的项目中,我们有过需要实现卡片堆叠动画和滑动删除效果的场景,这时候自定义LayoutManager和ItemAnimator就能发挥极大的作用,而这些都是ListView难以实现的。首先,ViewBinding的核心思想是通过预先生成的绑定类,将布局文件中的控件直接映射到代码中。比如,在实际开发中,我常常会看到以前在遗留项目中频繁出现的空指针问题,这在一定程度上是由于findViewById调用不当引起的,而ViewBinding可以在编译期就确保类型安全,极大地降低了这类常见错误的发生。

2025-05-12 18:48:52 680

原创 259.Movie APP (compose)

【代码】259.Movie APP (compose)

2025-05-11 11:11:11 162

原创 258.Travel App (Java)

【代码】258.Travel App (Java)

2025-05-07 15:59:28 150

原创 字节 懂车帝 (Android) 1,2面

那你的视频以什么形式来存储呢,比如一个视频我看了5秒,但 缓存到了10秒,然后我跳到了30秒,这是个什么缓存形式。现在让你做一个插件系统,你要让其他同学写的页面都在你的体系内成为一个插件,你要怎么设计,讲讲几个最核心的方法。如果让你去设计一个圆形的可以拖拽的进度条,然后进度条是渐变色的,怎么做。操作信号上有异常信号,然后常见的异常信号你了解哪些。讲讲你认为的卡顿,怎么优化,卡顿底层的原理是什么。讲讲你觉得那些编译器的插件是怎么管理和提供的呢。那讲讲看过的源码里你讲讲很好的设计。

2025-04-30 14:09:06 205

原创 小红书 社区 (Android) 1,2,3面

如果有100个任务,进入5个线程核心线程数,10个最大线程数,阻塞队列容量为20的线程池,如何运行,任务完成后,非核心线程和核心线程如何变化。Android中context是什么,有什么作用,Application里面的context和其他四大组件里的context有什么区别。假设我有两个Arraylist,然后里面分别传入int类型和string类型,最终获取这两个对象的class,如何比较它们。具体场景:一个ScrollVIew里有个按钮,点击按住不动,向上滑动,事件分发是怎么样的。

2025-04-28 20:21:33 455

原创 257.动态代理

与静态代理不同,静态代理需要手动为每个目标写出代理类,而动态代理通过反射机制在运行时生成代理类,这样可以更加灵活、通用,并且极大地降低了代码的重复量。简单来说,代理对象是客户端和目标对象之间的中介,通过代理对象,客户端调用目标对象的方法。在 invoke() 方法中,可以通过 Method.getAnnotation() 方法判断被调用的方法是否标记了 @Log 注解,如果标记了则进行日志记录,否则直接调用真实方法。这个类中,我们会在调用真实对象方法之前输出“调用前”日志,调用后输出“调用后”日志。

2025-04-28 09:28:22 625

原创 豆包 (Android) 一,二,三面

Java类加载机制是如何实现的,如果自定义一个String类,会怎么加载?讲讲注解 ,好了对你刚提到的注解有哪些是编译时那些是运行时的,哪些是通过反射实现的呢?方法A调用方法B,在操作系统或者JVM层面发生了什么,然后方法B的返回值是保存在哪里的。思考题:有一本很厚的英语书,如何使用最少得内存找出书中里面出现次数最多的单词。TCP三次握手知道吧,然后发送的第一个带有数据的包是第几个包,然后为什么。滑动窗口知道吧,然后滑动窗口的过程,窗口大小是怎么变化的。现在的操作系统的调度方式用的是哪种。

2025-04-27 20:50:43 179

原创 256.Doze 模式

WorkManager 会自动调整任务时间,但如果任务延迟过久可能会影响用户体验。────────────────────────────── 4. 在 Kotlin 中如何处理 Doze 模式。────────────────────────────── 3. 开发者在 Doze 模式下需要注意的点。────────────────────────────── 6. Doze 模式常见问题与调试建议。────────────────────────────── 2. Doze 模式的工作原理。

2025-04-27 20:23:44 572

原创 255.SDK (SDK开发)

SDK(Software Development Kit)是一套供其他开发者调用的库或工具集合,在 Android 平台上开发 SDK 意味着将某种功能或通用模块(如日志、统计、支付、网络请求、图片加载等)封装成一个库,然后发布给其他项目使用。使用者在项目中引用 SDK 后,只需要调用 MyLog.init() 来初始化,然后在需要的位置直接调用 MyLog.d()/MyLog.e() 等函数。这样,当你运行示例应用后,可以在 Logcat 中看到你的 SDK 输出的信息,并验证日志格式是否符合预期。

2025-04-27 20:08:59 783

原创 拼多多 (Android) 1,2面

如果让你设计一个线上的观察和上报的系统,用来检测一个软件之中是否发生了死锁,怎么设计。讲讲Socket,WebSocket ,然后有什么区别。创建进程和创建线程需要什么资源,创建过程会发生什么分配。C++和Java从源代码到最后在机器上执行,过程区别。用户登录时,用户名密码是放在POST的body里面吗。浏览器地址栏输入URL到出现页面,过程发生了什么。判断一棵树是不是AVL,不能用递归,然后要用栈。什么样的一个情况会造成死锁,怎么预防和避免。锁的操作和原子操作有什么区别。拥塞窗口的大小是如何决定的。

2025-04-23 12:26:40 219

原创 字节跳动:飞书 (Android) 一面 (拷打)

一个完整的时间,它有按下,然后移动,然后有抬起,然后再有抬起,如果VIew没有消费Touch_Down,那么后序的时间还能消费到吗。如果一个方法加上Synchronized的写实,一个静态方法加Synchronized有什么区别。那你知道shared_perference是什么吗?那用Retrofit的网络请求库,我要去增加一个API调用我要去怎么做。拦截器是怎么实现的没如果我有多个拦截器的话,怎么协调它们的工作。那我把LiveData放在一个普通的类里不行吗?虚引用你在什么场景喜爱用过吗?

2025-04-23 12:11:11 204

原创 腾讯视频 (Android) 一面

HTTP HTTPS TCP UDP GET POST HTTP状态码。分辨率 ,dp ,px。安卓怎么本地保存数据。

2025-04-23 11:54:45 308

原创 拼多多 (Android) 1,2,3面 (后端转来,没有安卓问题)

----------------------------------------------------------------(连续追问)手撕:有A,B两个文件,各有50亿个URL,电脑内存只有4G找出A,B中相同的URL。HTTPS中使用的是对称密钥还是非对称密钥。什么是DNS污染,以及如何防止中间人攻击。如何保证多线程导出的内容是顺序的。如何通过内存池和线程池提升性能。HTTPS加密通信是如何实现的。Java中类加载的流程是什么。如何处理大业务量对内存的影响。线程池主要是用来做什么的。

2025-04-23 11:51:14 112

原创 TME 腾讯 (一面)

场景题:如果我输入一个URL显示器显示连接失败,但是我DNS解析到IP地址了,ping这个IP地址以及端口都ping的通,你觉得是为什么。场景题:多线程任务下载一个文件,将文件分片下载,如果某个线程下载失败怎么办。一个1-5的随机数生成器,如何实现一个1-7的随机数生成器。思考题:无序链表中有重复的值,删掉重复的值,怎么做。场景题:合并文件的时候失败。

2025-04-23 07:51:01 136

原创 美团 (Android) 一面 (偏向基础方向)

讲到更底层的实现,其实在Java中泛型是通过“类型擦除”来实现的,也就是说,编译器在编译时会用实际的类型信息进行类型检查,但之后会删掉这个类型参数,把所有的泛型都当做Object或是它们的边界,所以有些限制,比如不能实例化泛型类型。你可以理解浅拷贝就是创建了一个新的对象,但它里面的成员变量,如果是基本类型数据,就会复制它们的值,但如果是引用类型,就只是把引用复制过去,也就是说新对象和原对象共享同一块内存区域。所以对于简单的数据,浅拷贝是够用的,但如果对象内部结构比较复杂,就可能出现意外的变化。

2025-04-22 20:27:23 398

原创 快手 (Android) 一,二面

举个例子,如果有一个“动物”类,里面可能包含基本行为,比如进食、移动,然后再设计猫、狗之类的子类,继承这些公共行为,同时根据各自的特点去重写或者增加独有的功能。总结来说,我会根据具体的需求选择对应的布局:简单线性排列就用LinearLayout,页面层叠简单的就用FrameLayout,需要相对定位用RelativeLayout,但随着更高级需求的出现,ConstraintLayout就成了大多数复杂布局的首选;就是说,抽象类里面可以写一些现成的实现逻辑,供子类直接使用,也可以让子类去实现自己的逻辑。

2025-04-22 16:23:13 665

原创 京东 (Android) 一面

基本上,当我们配置了Activity的launchMode为singleTop、singleTask或者singleInstance时,如果系统检测到你要启动这个Activity,而它已经在前台或者任务栈里存在,那么系统不会新建一个Activity实例,而是会把传入的Intent通过onNewIntent方法传递给这个已经存在的实例。在回溯过程中,你会试探性地往前走,每当发现当前的选择不可行,就回退一步,换一种可能的选择再试一遍,直到找到所有可行的解或者找到满足要求的解。首先,我会考虑歌词数据的格式。

2025-04-22 14:22:52 910

原创 科大讯飞 (Android)面经

首先,直接每次需要并发任务的时候都创建一个新线程,会带来线程创建和销毁的开销,这在高并发或者频繁执行任务的场景下,会导致系统资源浪费。线程的创建不仅需要分配内存,还涉及到操作系统线程调度,一旦创建过多的新线程,可能还会导致调度混乱或者系统上下文切换频繁,进一步拖慢整个应用的响应速度。这样的话,就避免了直接共享内存,从而大大降低了并发竞争的问题。你可以创建一个 actor,然后通过发送消息给它,让它按照顺序来处理,这样既能保证并发安全,又可以提高程序的整体响应能力,因为你不需要去上锁、解锁这些麻烦的操作。

2025-04-22 09:32:22 583

原创 百度 (Android)二面

哈希表能让数据访问更快,链表则记录了数据的使用顺序,这样每次访问一个元素,就可以把它从原来的位置移到链表的头部,这样队尾的就是最久没有使用的。在实际应用中,我们通常不会直接使用普通的二叉搜索树,而是使用一些自平衡的树结构,比如红黑树或者AVL树,这两种树都有机制自动调整树的结构,避免出现严重不平衡的情况。所谓的自平衡,就是在每次插入或者删除操作后,系统会检查树的平衡因子(或者其他度量方式),当发现不平衡时就进行旋转或其他调整操作,让树保持大致平衡,这样能确保大多数操作的时间复杂度保持在O(log n)。

2025-04-22 09:02:50 832

原创 快手 (Android) (1.2面)

首先,invalidate()主要用于刷新View的绘制,当我们的View数据改变或者状态需要改变时,调用invalidate()会告诉系统,“嘿,需要重新绘制这个View”。可能的话,还会考虑加上一些动态的空间分配策略,比如说如果高优先级的 View 占用的空间超出了一定比例,可以再做个限制,然后把剩下的空间平均分配或按照不同规则分配给低优先级的。总的来说,从我的角度看,atomic类提供了一种轻量级的线程安全方案,让我们可以在高并发场景下做到不加锁就能保证数据正确性,这是非常高效和实用的。

2025-04-21 17:14:45 889

原创 字节跳动 (Android) 一面

三大组件:Adapter、ViewHolder、LayoutManager。核心三脚架:Looper、MessageQueue、Handler。引用相等(==)与内容相等(equals)LiveData 在 MVVM 里的位置。Android 层面的内存优化和常见泄漏。RecyclerView 的定位和优势。子线程更新 LiveData 的做法。封装(Encapsulation)则让系统更灵活,可插拔,可扩展。(livedata是一个数据容器)多态(Polymorphism)继承(Inheritance)

2025-04-21 14:26:06 582

原创 254.Window

────────────────────────────── 【一、Window 的基本概念】在 Android 中,Window 代表了屏幕上一个可视区域,它是 View 层次结构与系统交互的桥梁。Window 包含了应用程序展示 UI 的一切内容,并由 WindowManager 管理。Window 本质上是一个抽象的概念,在 Activity、Dialog、Toast 等多个组件中都有涉及。常见的 Window 类型有:理解 Window 机制有助于我们在自定义界面、添加全局浮动窗口以及定制动画效果时

2025-04-20 15:06:13 647

原创 Android笔试题

A、实现应用程序间的数据共享B、是一段长的生命周期,没有用户界面的程序,可以保持应用在后台运行,而不会因为切换页面而消失C、可以实现界面间的切换,可以包含动作和动作数据,连接四大组件的纽带D、处理一个应用程序整体性的工作-----6. 下面关于BroadcastReceiver错误的是 (B D)A、BroadcastReceiver有两种注册方式,静态注册和动态注册。B、BroadcastReceiver必须在AndroidMainfest文件中声明。

2025-04-18 20:31:47 728

原创 253.TLS

总结一下,TLS 就是一套在不可靠网络(Internet)之上建立“可信通道”的协议,核心在握手阶段协商加密参数并交换密钥,随后所有数据都通过对称加密和消息认证保护。在 TCP 的三次握手过程中,所有的包(包括初始握手的 SYN 和 ACK 包)都是以明文形式传输的,攻击者可以轻松拦截并读取这些数据。1)记录层(Record Layer):负责把上层的应用数据(比如 HTTP 报文)分片、压缩、加密,然后打包到 TCP。TLS 握手过程(以 TLS 1.2 为例,TLS 1.3 略有简化)

2025-04-17 11:22:20 487

原创 其他面经汇总 (Android-深入)

你是怎么去学习网络协议的,网络协议的定义是什么,说一下网络协议的三个要素?说说二叉树是什么,在哪里会用到树这个数据结构,为什么会用树这个数据结构。使用HTTP协议传输一个10兆的文件,中途断了,如何实现断点重连。设计一个图片库APP,实现从服务端下载图片,以及本地缓存的实现。输入URL到渲染整个界面的一个过程,然后中间用了什么协议。让你设计一个牛客网系统,你会考虑什么,如何实现代码编译。对OKHTTP的了解然后这个框架的设计怎么样。APP的页面突然卡了一下,怎么排查。进程的调度方式,线程的调度方式。

2025-04-16 15:34:57 251

原创 对于主(1,2面)面经的回答

而Android虚拟机,最初是Dalvik虚拟机,后来演变成了Android Runtime (ART),它也是为了实现跨硬件平台运行Android应用而设计的,主要支持Java或Kotlin等语言编写的代码,但在实现上做了专门针对移动设备优化的处理。在这个阶段,不仅要确定View的最终尺寸,还要考虑子View的尺寸,对于那些有多层嵌套结构的ViewGroup而言,合理地测量每个子View是非常关键的,这样才能确保布局显示的合理性。需要注意的是,在使用Handler时,我们要特别关注内存泄露的问题。

2025-04-15 09:30:26 435

原创 252.动态代理

动态代理的核心在于运行期生成一个新的类,该类实现了目标接口,并拦截目标对象的方法调用,将方法调用信息传递给InvocationHandler。本文旨在详细讲解Kotlin中的动态代理机制,帮助Android开发者理解其基本概念、动态代理的实现原理以及在实际项目中的使用方式,同时通过完整示例,从头到尾展示如何在Kotlin项目中使用动态代理。实现方式类似于本文中的示例,我们只需提供一个统一的InvocationHandler,并通过代理工厂创建代理对象,将原有业务逻辑传入,便可实现功能复用。

2025-04-13 16:03:02 846

原创 关于(中等,困难)面经的回答(第二部分)

Android四大组件(以及Application)的onCreate/onReceiver的方法中Threadsleep()。分别发生在什么时候,JVM栈中存储的什么,堆内存中存储的是什么。创建了几个String对象?Activity的4大启动模式,与开发中需要注意的问题,如onNewIntent()的调用。View的绘制流程是从Activity的哪个生命周期方法开始执行的。判断对象是否被回收,有哪些GC算法,虚拟机使用最多的是什么算法。ThreadLocal的原理,以及在Looper是如何应用的?

2025-04-13 09:39:23 435

原创 251.AIDL

当你的应用需要和运行在不同进程中的组件进行通信时,就需要使用 AIDL。客户端通过 bindService() 方法绑定 Service,通过 IMyAidlInterface.Stub.asInterface() 方法获取接口对象,然后调用方法执行操作。创建一个 .aidl 文件,定义接口及方法。实现 AIDL 接口并在 Service 的 onBind() 方法中返回生成的 Binder 对象,供客户端绑定后调用。────────────────────────────── ■ AIDL 概念和用法。

2025-04-08 15:13:26 380

原创 关于 (中等,困难)面经的回答 (第一部分)

最重要的一点是,它的生命周期不依赖于启动服务的组件,除非你显式调用stopService()或者在服务内部调用stopSelf()来结束服务,否则服务会一直存在,系统也可能给予它一定的容错性以保持业务的连续性。当系统检测到即将发生诸如配置变化、内存不足或Activity被销毁的情况时,会在销毁前调用onSaveInstanceState(),在这个回调里,我们可以将需要保存的临时状态,比如UI控件的当前状态、输入的数据或者一些关键的变量状态放到一个Bundle对象中。

2025-04-06 11:10:05 932

原创 海盗分金 (博弈论-思维)【面试】

若1号被否决,5号在2号方案中得2枚,但若1号直接给5号1枚,5号可能反对(因收益相同,倾向杀人)。若3号被否决,轮到4号分配,4号会独吞100枚(因4号自己的一票即过半),5号得0。5号支持(2 > 在2号方案中可能的2,但避免风险)。:97(自留),0(3号),1(4号),2(5号)。:97(自留)、0、1、0、2(分别对应1-5号)。若2号被否决,3号会分配(99, 0, 1)。:99(自留)、0(4号)、1(5号)。,只要3号给其1枚,5号必定支持。1号+3号+5号共3票,通过方案。

2025-04-05 11:17:45 526

原创 250.TouchDelegate

TouchDelegate 本质上是一个委托机制,它允许将父 View 的指定区域内的触摸事件转发给一个指定的子 View ,从而实现“扩展”该子 View 的触摸响应区域。这样,在父容器分发触摸事件时,会优先检测扩展区域内的触摸点,并将事件转发给目标 View 处理。首先,我们要确定需要扩展触摸区域的目标 View 及其父容器。在一些自定义控件中,可能需要根据不同区域响应不同的触摸事件,或者在组件周边预留容错范围,这时可以利用 TouchDelegate 将某个区域的事件集中交给特定的 View 处理。

2025-04-05 10:28:00 919

原创 249.侧边索引

当用户在侧边索引上点击或拖动时,对应的字母会作为回调参数传递至 MainActivity,在 MainActivity 中我们通过提前计算好的 Map(letterPosMap)来决定 RecyclerView 应该滚动的位置,并调用 scrollToPositionWithOffset() 方法实现精准定位。举例来说,如果列表项为联系人姓名,则首先提取每个联系人的首字母,然后根据字母排序。此外,还可以在界面中显示一个浮动提示(Toast 或自定义的悬浮 View),显示当前选中的字母,以增强用户体验。

2025-04-01 16:40:25 868

原创 关于 (杂)面经的回答

进程(Process)进程是操作系统中资源分配的基本单位。每个进程都有独立的内存空间和系统资源,比如文件句柄、网络连接等。进程是一个正在执行的程序实例,它包含了程序代码、数据、堆栈和一些处理器状态信息。线程(Thread)线程是进程中的一个执行单元,是CPU调度和执行的基本单位。一个进程可以包含多个线程,这些线程共享进程的内存空间和资源。线程有自己的寄存器状态和栈,但它们共享进程的代码段、数据段和其他资源。用户点击按钮触发了一系列事件,从系统捕获点击事件,到视图处理,再到执行点击监听器中的逻辑。

2025-04-01 09:25:28 829

原创 Android面试补充题 (中等 还有困难)

1.ActivityA启动ActivitwyB会调用哪些方法,如果B是透明主题或者是DialogActivity呢?2.说一下onSaveInstanceState()方法的作用?何时会被调用3.Activity的启动模式和使用场景4.ActivityA跳转ActivityB,再按返回键,生命周期执行的顺序5.onStart onResume onPause onStop的区别6.Activity之间传递数据的方式Intent是否有大小限制,如果传递的数据量偏大,有哪些方案。

2025-03-31 19:19:12 660

原创 总(主1,2面) -(Android开发)面经问题汇总

19.TCP的三次握手,四次挥手,然后挥手过程中主要方的动态是什么。1.Handler流程,它使用不当会造成内存泄漏吗,为什么。1.ArrayList和LinkedList的区别。6.讲一个红黑树和一个排序算法的时间复杂的分析思路。12.java虚拟机和Android虚拟机的区别。1.局部变量和全局变量 (重复的我就不写了)5.service和activity的区别。18.TCP和UDP的使用场景有什么不同。12.HTTP请求GET和POST的区别。3.多线程的同步问题,怎么保证线程安全。

2025-03-31 17:12:53 281

电影APP点赞,介绍,内容讲解

直接AS打开即可

2025-05-11

旅行景点推荐评分APP

解压后AS打开

2025-05-07

直接复制,然后粘贴到assert下面

直接复制,然后粘贴到assert下面

2025-03-06

百度一面 ,直接打开即可

百度一面 ,直接打开即可

2025-03-03

快手客户端(一面) 直接打开即可

快手客户端(一面) 直接打开即可

2025-02-27

美团Android客户端(一面),直接下载打开

美团Android客户端(一面),直接下载打开

2025-02-26

直接解压后打开 用Android Stdio

直接解压后打开 用Android Stdio

2025-02-17

多线程,停车场管理系统(文件)

多线程,停车场管理系统(文件)

2025-01-23

文件IO作业 (Java)

解压后idea打开

2025-01-21

(Java)集合类作业

解压后用idea打开

2025-01-20

类与对象作业 (Java)

解压后用idea打开

2025-01-20

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除