### Initialize SDK Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/README.md Initialize the SDK instance with context, UID, and token. ```java WKIM.getInstance().init(context, uid, token); ``` -------------------------------- ### Connect to Server Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/README.md Initiate the connection to the WukongIM server. ```java WKIM.getInstance().getConnectionManager().connection(); ``` -------------------------------- ### WKDBHelper 异步查询基础设施 Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ANR_FIX_SUMMARY.md 定义用于数据库异步操作的线程池、主线程 Handler 以及通用查询回调接口。 ```java // 单线程池,保证数据库操作顺序性 private static final ExecutorService dbExecutor = Executors.newSingleThreadExecutor(); // 主线程 Handler,用于回调 private static final Handler mainHandler = new Handler(Looper.getMainLooper()); ``` ```java public interface QueryCallback { T onQuery(Cursor cursor); // 后台线程处理 void onResult(T result); // 主线程回调 } ``` ```java // 异步原始 SQL 查询 public void rawQueryAsync(String sql, Object[] selectionArgs, QueryCallback callback) // 异步 SELECT 查询 public void selectAsync(String table, String selection, String[] selectionArgs, String orderBy, QueryCallback callback) ``` -------------------------------- ### Add Gradle Dependency Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/README.md Include the SDK in your project's build.gradle file. ```groovy implementation 'com.github.WuKongIM:WuKongIMAndroidSDK:version' // 版本号请看上面 ``` -------------------------------- ### 使用 WKDBHelper 直接异步查询 Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md 直接调用 rawQueryAsync 处理 Cursor 数据转换并在主线程接收结果。 ```java String sql = "SELECT * FROM reminders WHERE channel_id=? AND done=?"; Object[] args = new Object[]{channelID, 0}; WKIMApplication.getInstance().getDbHelper().rawQueryAsync(sql, args, new WKDBHelper.QueryCallback>() { @Override public List onQuery(Cursor cursor) { // ✅ 后台线程:处理 Cursor List list = new ArrayList<>(); if (cursor != null) { for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { WKReminder reminder = serializeReminder(cursor); list.add(reminder); } } return list; } @Override public void onResult(List result) { // ✅ 主线程:更新 UI updateUI(result); } } ); ``` -------------------------------- ### Configure JitPack Repository Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/README.md Add the JitPack repository to your project's build.gradle file. ```groovy allprojects { repositories { maven { url 'https://jitpack.io' } } } ``` -------------------------------- ### Migrate UI Refresh to Async Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md Replace direct synchronous database queries in UI event callbacks with asynchronous methods to maintain UI responsiveness. ```java @Override public void onRefresh() { // ❌ 主线程数据库查询 List list = ReminderDBManager.getInstance() .queryWithChannelAndDone(channelID, channelType, 0); adapter.setData(list); swipeRefreshLayout.setRefreshing(false); } ``` ```java @Override public void onRefresh() { // ✅ 异步查询 ReminderDBManager.getInstance().queryWithChannelAndDoneAsync( channelID, channelType, 0, reminders -> { adapter.setData(reminders); swipeRefreshLayout.setRefreshing(false); } ); } ``` -------------------------------- ### 定义异步查询方法签名 Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md WKDBHelper 中用于执行异步 SQL 和 SELECT 查询的方法定义。 ```java public void rawQueryAsync(String sql, Object[] selectionArgs, QueryCallback callback) ``` ```java public void selectAsync(String table, String selection, String[] selectionArgs, String orderBy, QueryCallback callback) ``` -------------------------------- ### Implement Pagination for Large Datasets Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md Use LIMIT and OFFSET clauses to load data in chunks rather than fetching entire tables. ```java String sql = "SELECT * FROM reminders WHERE channel_id=? " + "ORDER BY message_seq DESC LIMIT ? OFFSET ?"; Object[] args = {channelID, pageSize, offset}; ``` -------------------------------- ### Asynchronous Database Query Implementation in Fragment Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md Demonstrates loading data asynchronously using ReminderDBManager and updating the UI within a Fragment. Always verify the Fragment's lifecycle state before updating UI components inside the callback. ```java // ChatFragment.java public class ChatFragment extends Fragment { private RecyclerView recyclerView; private ReminderAdapter adapter; @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // 初始化 UI recyclerView = view.findViewById(R.id.recycler_view); adapter = new ReminderAdapter(); recyclerView.setAdapter(adapter); // 加载数据(异步) loadReminders(); } private void loadReminders() { // 显示加载状态 showLoading(true); // 异步查询数据库 ReminderDBManager.getInstance().queryWithChannelAndDoneAsync( channelID, channelType, 0, reminders -> { // 检查 Fragment 状态 if (!isAdded() || getView() == null) { return; } // 更新 UI showLoading(false); adapter.setData(reminders); // 如果数据为空,显示空视图 if (reminders.isEmpty()) { showEmptyView(); } } ); } private void showLoading(boolean show) { // 显示/隐藏加载动画 } private void showEmptyView() { // 显示空数据提示 } } ``` -------------------------------- ### Manage Lifecycle in Async Callbacks Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md Verify the existence of Fragment or Activity before updating the UI to avoid memory leaks or crashes. ```java @Override public void onViewCreated(View view, Bundle savedInstanceState) { loadData(); } private void loadData() { ReminderDBManager.getInstance().queryWithChannelAndDoneAsync( channelID, channelType, 0, reminders -> { // ✅ 检查 Fragment 是否还存在 if (isAdded() && getView() != null) { updateUI(reminders); } } ); } ``` -------------------------------- ### StrictMode 严格模式检测 Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ANR_FIX_SUMMARY.md 在 Application 中配置严格模式,用于在 Debug 环境下检测主线程数据库调用。 ```java // 在 Application 中开启严格模式(Debug 模式) if (BuildConfig.DEBUG) { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads() .detectDiskWrites() .penaltyLog() .penaltyDeath() // 崩溃,强制修复 .build()); } ``` -------------------------------- ### Fragment 生命周期检查 Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ANR_FIX_SUMMARY.md 在异步回调中检查 Fragment 状态,防止在 Fragment 销毁后更新 UI。 ```java if (isAdded() && getView() != null) { updateUI(result); } ``` -------------------------------- ### ProGuard Rules Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/README.md Add these rules to your proguard-rules.pro file to prevent necessary classes from being obfuscated. ```text -dontwarn com.xinbida.wukongim.** -keep class com.xinbida.wukongim.**{*;} #数据库加密 -keep,includedescriptorclasses class net.sqlcipher.** { *; } -keep,includedescriptorclasses interface net.sqlcipher.** { *; } #--------- 混淆dh curve25519------- -keep class org.whispersystems.curve25519.**{*;} -keep class org.whispersystems.** { *; } -keep class org.thoughtcrime.securesms.** { *; } ``` -------------------------------- ### 数据库索引优化 Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ANR_FIX_SUMMARY.md 通过创建索引提升查询性能。 ```sql CREATE INDEX idx_reminders_channel ON reminders(channel_id, channel_type, done); ``` -------------------------------- ### Set IP and Port Listener Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/README.md Register a listener to provide the socket IP and port to the SDK. ```java WKIM.getInstance().getConnectionManager().addOnGetIpAndPortListener(new IGetIpAndPort() { @Override public void getIP(IGetSocketIpAndPortListener iGetSocketIpAndPortListener) { // 可请求接口后返回到sdk iGetSocketIpAndPortListener.onGetSocketIpAndPort("xxx.xxx.xxx",6666); } }); ``` -------------------------------- ### Listen for Command Messages Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/README.md Register a listener to handle command (CMD) messages. ```java WKIM.getInstance().getCMDManager().addCmdListener("listener_key", new ICMDListener() { @Override public void onMsg(WKCMD cmd) { // todo } }); ``` -------------------------------- ### 定义查询回调接口 Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md QueryCallback 接口用于处理后台线程的 Cursor 数据转换以及主线程的结果回调。 ```java public interface QueryCallback { // 在后台线程执行,处理 Cursor T onQuery(Cursor cursor); // 在主线程执行,接收查询结果 void onResult(T result); } ``` -------------------------------- ### Listen for New Messages Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/README.md Register a listener to receive incoming messages. ```java WKIM.getInstance().getMsgManager().addOnNewMsgListener("listener_key", new INewMsgListener() { @Override public void newMsg(List list) { // todo } }); ``` -------------------------------- ### Listen for Connection Status Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/README.md Register a listener to monitor the connection status changes. ```java WKIM.getInstance().getConnectionManager().addOnConnectionStatusListener("listener_key",new IConnectionStatus() { @Override public void onStatus(int status) { // 0 失败 【WKConnectStatus.fail】 // 1 成功 【WKConnectStatus.success】 // 2 被踢 【WKConnectStatus.kicked】 // 3 同步消息中【WKConnectStatus.syncMsg】 // 4 连接中 【WKConnectStatus.connecting】 // 5 无网络连接 【WKConnectStatus.noNetwork】 } }); ``` -------------------------------- ### 异步化设计冲突示例 Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ANR_FIX_SUMMARY.md 说明为什么不能直接修改现有同步方法为异步,因为这会导致返回值冲突和调用方崩溃。 ```java // 同步方法 Cursor cursor = dbHelper.rawQuery(sql); // 立即返回 cursor.moveToFirst(); // 马上使用 // 如果改成异步 Cursor cursor = dbHelper.rawQuery(sql); // 返回什么?null? cursor.moveToFirst(); // 💥 NullPointerException ``` -------------------------------- ### ReminderDBManager 异步扩展 Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ANR_FIX_SUMMARY.md 保留原有同步方法并标记为过期,同时新增异步查询方法及对应的回调接口。 ```java @Deprecated public List queryWithChannelAndDone(String channelID, byte channelType, int done) ``` ```java public void queryWithChannelAndDoneAsync(String channelID, byte channelType, int done, ReminderQueryCallback callback) ``` ```java public interface ReminderQueryCallback { void onResult(List reminders); } ``` -------------------------------- ### 使用 ReminderDBManager 异步查询 Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md 通过封装好的异步方法在主线程调用,并在 onResult 回调中更新 UI。 ```java // 在主线程调用异步查询 public void refreshUI() { ReminderDBManager.getInstance().queryWithChannelAndDoneAsync( channelID, channelType, 0, new ReminderDBManager.ReminderQueryCallback() { @Override public void onResult(List reminders) { // ✅ 这里已经在主线程,可以直接更新 UI updateUI(reminders); } } ); } ``` -------------------------------- ### 使用 Lambda 表达式异步查询 Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md 在支持 Java 8+ 的环境中使用 Lambda 简化异步回调代码。 ```java ReminderDBManager.getInstance().queryWithChannelAndDoneAsync( channelID, channelType, 0, reminders -> updateUI(reminders) // 主线程回调 ); ``` -------------------------------- ### Implement Caching for Database Queries Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md Use a local Map to store query results and reduce redundant database access. ```java private Map> reminderCache = new HashMap<>(); public void getReminderListWithCache(String channelID, byte channelType, ReminderQueryCallback callback) { String key = channelID + "_" + channelType; // 先检查缓存 if (reminderCache.containsKey(key)) { callback.onResult(reminderCache.get(key)); return; } // 缓存未命中,查询数据库 queryWithChannelAndDoneAsync(channelID, channelType, 0, reminders -> { reminderCache.put(key, reminders); callback.onResult(reminders); }); } ``` -------------------------------- ### Listen for Message Acknowledgement Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/README.md Register a listener to receive delivery status updates for sent messages. ```java WKIM.getInstance().getMsgManager().addSendMsgAckListener("listener_key", new ISendACK() { @Override public void msgACK(long clientSeq, String messageID, long messageSeq, byte reasonCode) { // clientSeq 客户端序列号 // messageID 服务器消息ID // messageSeq 服务器序列号 // reasonCode 消息状态码【0:发送中1:成功2:发送失败3:不是好友或不在群内4:黑名单】 } }) ``` -------------------------------- ### Optimize Queries with Batch Processing Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md Replace multiple individual queries with a single batch query using the IN clause to improve performance. ```java // ❌ 低效:N 次查询 for (String channelId : channelIds) { queryWithChannelAndDoneAsync(channelId, channelType, 0, callback); } // ✅ 高效:1 次批量查询 String sql = "SELECT * FROM reminders WHERE channel_id IN (" + placeholders + ") AND done=?"; rawQueryAsync(sql, args, callback); ``` -------------------------------- ### 同步查询错误用法 Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md 在主线程直接调用同步查询会导致 UI 线程阻塞,引发 ANR。 ```java // 在主线程直接调用同步查询 public void refreshUI() { // ⚠️ 这会阻塞主线程,导致 ANR List list = ReminderDBManager.getInstance() .queryWithChannelAndDone(channelID, channelType, 0); updateUI(list); } ``` -------------------------------- ### Refactor WKUIConversationMsg Database Access Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md Convert synchronous getter methods that block the calling thread into asynchronous patterns. ```java // WKUIConversationMsg.java public List getReminderList() { // ❌ 同步查询,会阻塞调用线程 return ReminderDBManager.getInstance() .queryWithChannelAndDone(channelID, channelType, 0); } ``` ```java // WKUIConversationMsg.java public void getReminderList(ReminderDBManager.ReminderQueryCallback callback) { ReminderDBManager.getInstance() .queryWithChannelAndDoneAsync(channelID, channelType, 0, callback); } // 使用处 conversationMsg.getReminderList(reminders -> { // 更新 UI updateReminderList(reminders); }); ``` ```java // WKUIConversationMsg.java private List cachedReminderList; // 异步加载 public void loadReminderList(ReminderDBManager.ReminderQueryCallback callback) { if (cachedReminderList != null) { callback.onResult(cachedReminderList); return; } ReminderDBManager.getInstance().queryWithChannelAndDoneAsync( channelID, channelType, 0, reminders -> { cachedReminderList = reminders; callback.onResult(reminders); } ); } // 获取缓存 public List getCachedReminderList() { return cachedReminderList != null ? cachedReminderList : new ArrayList<>(); } ``` -------------------------------- ### Handle Async Callbacks Safely Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ASYNC_DB_USAGE.md Avoid performing heavy operations inside callbacks to prevent blocking the main thread. ```java @Override public void onResult(List result) { // ❌ 错误:主线程执行耗时操作 for (WKReminder r : result) { heavyProcessing(r); // 耗时操作 } // ✅ 正确:只更新 UI adapter.setData(result); } ``` -------------------------------- ### ANR 修复前后对比 Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/docs/ANR_FIX_SUMMARY.md 展示从主线程同步查询到异步查询的重构方式。 ```java @Override public void onRefresh() { // ❌ 主线程同步查询 List list = ReminderDBManager.getInstance() .queryWithChannelAndDone(channelID, channelType, 0); updateUI(list); } ``` ```java @Override public void onRefresh() { // ✅ 异步查询 ReminderDBManager.getInstance().queryWithChannelAndDoneAsync( channelID, channelType, 0, reminders -> updateUI(reminders) ); } ``` -------------------------------- ### Send Message Source: https://github.com/wukongim/wukongimandroidsdk/blob/master/README.md Send a text message to a specific channel. ```java WKIM.getInstance().getConnectionManager().sendMessage(new WKTextContent("我是文本消息"), channelID, channelType); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.