上一篇
安卓从服务器获取数据库
- 行业动态
- 2025-04-24
- 3035
安卓通过HTTP请求调用服务器API接口,获取JSON格式数据后解析,再存入本地Room数据库实现数据同步
服务器端准备
搭建API接口
- 服务器需提供RESTful API,支持
GET
请求获取数据(如JSON格式)。 - 示例接口:
https://example.com/api/users
返回用户列表。
- 服务器需提供RESTful API,支持
数据格式
- 常见格式:JSON(如数组或对象)。
- 示例返回值:
[ {"id":1, "name":"Alice", "email":"alice@example.com"}, {"id":2, "name":"Bob", "email":"bob@example.com"} ]
安卓客户端实现
添加依赖库
在build.gradle
中添加以下依赖:
// Retrofit(网络请求) implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // Room(本地数据库) implementation 'androidx.room:room-runtime:2.5.1' annotationProcessor 'androidx.room:room-compiler:2.5.1' // Lifecycle(可选,用于数据响应式处理) implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1'
定义数据模型
创建与JSON对应的实体类:
// User.java @Entity(tableName = "users") public class User { @PrimaryKey public int id; public String name; public String email; }
配置Retrofit
创建接口定义API:
// ApiService.java public interface ApiService { @GET("api/users") Call<List<User>> getUsers(); // 同步调用 // 或使用RxJava/Coroutines支持异步 }
初始化Retrofit实例:
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://example.com/") // 替换为实际服务器地址 .addConverterFactory(GsonConverterFactory.create()) .build(); ApiService apiService = retrofit.create(ApiService.class);
发起网络请求并解析数据
同步调用示例(需在子线程执行):
new Thread(() -> { try { Response<List<User>> response = apiService.getUsers().execute(); List<User> users = response.body(); // 将数据存入数据库 } catch (IOException e) { e.printStackTrace(); } }).start();
异步调用示例(回调处理):
apiService.getUsers().enqueue(new Callback<List<User>>() { @Override public void onResponse(Call<List<User>> call, Response<List<User>> response) { if (response.isSuccessful()) { List<User> users = response.body(); // 存入数据库 } } @Override public void onFailure(Call<List<User>> call, Throwable t) { // 处理错误 } });
将数据存入Room数据库
配置Room数据库:
// AppDatabase.java @Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); } // UserDao.java @Dao public interface UserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) void insertAll(List<User> users); @Query("SELECT FROM users") LiveData<List<User>> getAllUsers(); }
插入数据到数据库:
AppDatabase db = Room.databaseBuilder(context, AppDatabase.class, "app_db").build(); db.userDao().insertAll(users); // users为网络请求获取的列表
在UI中观察数据变化
使用LiveData
监听数据库更新:
UserDao userDao = db.userDao(); userDao.getAllUsers().observe(this, users -> { // 更新RecyclerView等UI组件 });
常见问题与优化
问题 | 解决方案 |
---|---|
网络请求失败 | 检查服务器地址、网络权限(INTERNET ),或使用OkHttp 添加日志。 |
主线程异常 | 网络操作需在子线程执行,或使用enqueue 异步回调。 |
数据重复插入 | 在Room 中使用OnConflictStrategy.REPLACE 或添加唯一索引。 |
内存溢出(大数据集) | 分页加载数据,或使用PagingSource 结合Paging3 库。 |
相关问题与解答
问题1:如何处理网络请求的缓存?
解答:
可使用OkHttp
的缓存功能或Retrofit
的@Headers
注解强制缓存。
OkHttpClient client = new OkHttpClient.Builder() .cache(new Cache(context.getCacheDir(), 10 1024 1024)) // 10MB缓存 .build(); Retrofit retrofit = new Retrofit.Builder() .client(client) .build();
服务器需支持HTTP
缓存头(如Cache-Control
)。
问题2:如何优化数据库的频繁写入?
解答:
- 批量插入:使用
insertAll
代替单条插入,减少事务开销。 - 协程/线程池:在IO线程执行数据库操作,避免阻塞主线程。
- 数据合并:先查询本地是否存在,仅插入新数据或更新变化字段