元婴期
15. 如何在 Android 中实现网络请求?如何使用 Retrofit 和 OkHttp?
Retrofit
和 OkHttp
是 Android
中广泛使用的网络请求库,提供了简化的 HTTP
请求和响应处理。
Retrofit
的使用
添加依赖
在
build.gradle
中添加Retrofit
和OkHttp
依赖。implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.okhttp3:okhttp:4.9.1'
定义
API
接口public interface ApiService { @GET("posts") Call<List<Post>> getPosts(); }
创建
Retrofit
实例Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://jsonplaceholder.typicode.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); ApiService apiService = retrofit.create(ApiService.class);
发起请求
apiService.getPosts().enqueue(new Callback<List<Post>>() {
@Override
public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
// 处理成功响应
}
@Override
public void onFailure(Call<List<Post>> call, Throwable t) {
// 处理请求失败
}
});
OkHttp
的使用
OkHttp
是一个底层的 HTTP
请求库,Retrofit
的网络请求是基于 OkHttp
实现的。
示例
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts")
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// 处理请求失败
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// 处理成功响应
}
});
Retrofit
提供了高层次的封装,适合简化 API
调用,而 OkHttp
更灵活,可以处理复杂的网络需求。
16. 如何在 Android 中使用 Jetpack 库?Jetpack 的核心组件有哪些?
Jetpack
是一套由 Android
官方提供的库,简化了常见的 Android
开发任务。
它包含了多种工具和架构组件,帮助开发者更高效地开发稳定且可维护的应用。
Jetpack
的核心组件
LiveData
:一个具有生命周期感知的数据持有者,能够自动更新UI
。ViewModel
:帮助管理UI
数据,确保数据在Activity/Fragment
重建时保留。Navigation
:简化Fragment
和Activity
之间的导航,提供图形化的导航控制。Room
:一个持久化库,提供了对SQLite
数据库的更简洁、安全的操作。WorkManager
:用于管理后台任务,即使应用退出或设备重启,任务依然能够可靠地执行。Data Binding
:简化了UI
和数据的绑定过程,减少了代码重复。
使用 Jetpack
的示例
// 通过 ViewModel 和 LiveData 管理 UI 数据
public class MyViewModel extends ViewModel {
private MutableLiveData<String> liveData = new MutableLiveData<>();
public LiveData<String> getLiveData() {
return liveData;
}
public void setLiveData(String value) {
liveData.setValue(value);
}
}
17. 如何在 Android 中进行依赖注入?什么是 Dagger 或 Hilt?
依赖注入(DI) 是一种设计模式,允许对象的依赖通过构造函数、方法或属性注入,而不是直接在类中实例化。
Dagger
和 Hilt
是 Android
中常用的依赖注入框架。
Dagger
是一个完全静态的依赖注入框架,提供了高效的依赖注入实现,它通过注解生成依赖关系的代码。
Hilt
是基于 Dagger
的依赖注入库,简化了在 Android
项目中使用依赖注入的复杂性,特别是与 Android
生命周期和 ViewModel
集成得很好。
使用 Hilt
的步骤
添加依赖
在
build.gradle
中添加Hilt
依赖。implementation "com.google.dagger:hilt-android:2.38.1" kapt "com.google.dagger:hilt-android-compiler:2.38.1"
初始化
Hilt
在
Application
类上加上@HiltAndroidApp
注解。@HiltAndroidApp public class MyApplication extends Application { }
注入依赖
在
Activity
或Fragment
中通过@Inject
注解注入依赖:@AndroidEntryPoint public class MyActivity extends AppCompatActivity { @Inject MyRepository repository; }
Hilt
简化了 Dagger
的使用,自动处理依赖关系的生成和注入,适合 Android
开发。
18. 如何在 Android 中优化性能?有哪些常见的性能优化策略?
减少主线程阻塞
- 将耗时操作(如网络请求、数据库访问)放在后台线程中执行,避免
ANR
(应用无响应)。
- 将耗时操作(如网络请求、数据库访问)放在后台线程中执行,避免
使用
RecyclerView
代替ListView
RecyclerView
更加高效,尤其是处理大数据集时,可以实现更加流畅的滚动效果。
内存优化
- 避免内存泄漏,及时释放不再使用的对象,特别是上下文引用。使用
LeakCanary
等工具检测内存泄漏。
- 避免内存泄漏,及时释放不再使用的对象,特别是上下文引用。使用
减少过度绘制
- 在
UI
布局设计中,减少View
的嵌套和重叠,使用ConstraintLayout
来优化布局层级。
- 在
懒加载数据
- 仅在需要时加载数据,避免一次性加载所有资源。通过分页加载数据提高响应速度。
使用
Bitmap
优化图片加载- 在处理图片时,使用合适的分辨率和压缩方式,避免加载过大的图片。
19. 如何在 Android 中处理不同屏幕尺寸和分辨率的适配问题?
Android
设备有各种不同的屏幕尺寸和分辨率,因此开发者需要进行适配,以确保应用在所有设备上都能正确显示。
使用
dp
和sp
单位dp
(独立像素)用于布局中的尺寸,sp
(可缩放像素)用于字体大小,这两者都可以根据设备的密度进行自动缩放。
使用
ConstraintLayout
- 通过
ConstraintLayout
可以创建更加灵活、动态的布局,减少对特定屏幕尺寸的依赖。
- 通过
创建多套资源
- 在
res
目录中为不同的屏幕尺寸提供不同的布局和图像资源。例如:res/layout-sw600dp/
适用于宽度在600dp
以上的平板设备。res/drawable-hdpi/
提供适用于高密度屏幕的图片资源。
- 在
自适应布局
- 使用
wrap_content
和match_parent
使控件根据内容和父容器的大小自动调整,减少硬编码的宽高值。
- 使用
20. 如何在 Android 中进行内存管理?如何防止内存泄漏?
Android
中的内存管理通过 Garbage Collector (GC)
自动处理,但开发者仍然需要注意避免内存泄漏和过度的内存使用。
避免持有对
Context
的静态引用- 不要在静态变量中保存
Activity
或Fragment
的引用,这样会导致GC
无法回收内存。
- 不要在静态变量中保存
使用
WeakReference
- 在某些场景下(如
Handler
或AsyncTask
),可以使用WeakReference
保存对象的引用,避免长时间持有导致内存泄漏。
- 在某些场景下(如
关闭资源
- 在使用完资源后(如
Cursor
、文件流等),及时关闭它们,释放占用的内存。
- 在使用完资源后(如
检测内存泄漏
- 使用
LeakCanary
等工具检测内存泄漏,帮助找到问题源头。
- 使用
示例
// 使用 WeakReference 避免内存泄漏 private static class MyHandler extends Handler { private final WeakReference<MainActivity> activityReference; MyHandler(MainActivity activity) { activityReference = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { MainActivity activity = activityReference.get(); if (activity != null) { // 处理消息 } } }
21. 如何在 Android 中实现动态权限请求?如何处理用户的权限授权?
在
Manifest
文件中声明权限<uses-permission android:name="android.permission.CAMERA" />
检查权限
在运行时检查应用是否已获得权限。
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { // 请求权限 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, CAMERA_REQUEST_CODE); }
处理权限请求结果
重写
onRequestPermissionsResult()
方法处理用户的授权结果。@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == CAMERA_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限已授予 } else { // 权限被拒绝 } } }
动态权限请求在运行时进行,用户可以选择允许或拒绝权限。应用应当处理用户拒绝权限的情况,并提供适当的反馈或提示。