优化启动页启动速度。
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sat Dec 13 03:05:50 GMT 2025
|
||||
#Sat Dec 13 03:34:07 GMT 2025
|
||||
stageCount=1
|
||||
libraryProject=
|
||||
baseVersion=15.12
|
||||
publishVersion=15.12.0
|
||||
buildCount=78
|
||||
buildCount=80
|
||||
baseBetaVersion=15.12.1
|
||||
|
||||
@@ -11,6 +11,8 @@ import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.telecom.TelecomManager;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@@ -44,7 +46,8 @@ import java.util.List;
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/08/30 14:32
|
||||
* @Describe Contacts 主窗口(完全适配 API 30 + Java 7 语法)
|
||||
* 核心优化:1. 移除电话状态监听 2. 移除通话筛选服务 3. 移除 MainService 所有相关逻辑 4. 保留原有页面结构
|
||||
* 核心优化:1. 移除电话状态监听 2. 移除通话筛选服务 3. 移除 MainService 所有相关逻辑 4. ViewPager 实现 Fragment 懒加载(仅首屏初始化)
|
||||
* 问题修复:解决首屏 Fragment 空白问题(删除 setPrimaryItem 冲突逻辑+延迟首屏初始化)
|
||||
*/
|
||||
public final class MainActivity extends WinBollActivity implements IWinBoLLActivity, ViewPager.OnPageChangeListener, View.OnClickListener {
|
||||
|
||||
@@ -85,6 +88,8 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
|
||||
private int currentPoint = 0;
|
||||
private List<Fragment> fragmentList;
|
||||
private List<String> tabTitleList;
|
||||
// 记录已初始化的Fragment位置(避免重复初始化)
|
||||
private boolean[] isFragmentInit;
|
||||
|
||||
// ====================== 6. 接口实现区 ======================
|
||||
@Override
|
||||
@@ -138,6 +143,16 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
|
||||
mADsBannerView.releaseAdResources();
|
||||
LogUtils.d(TAG, "onDestroy: 广告栏资源已释放");
|
||||
}
|
||||
// 清空Fragment相关引用,避免内存泄漏
|
||||
if (fragmentList != null) {
|
||||
fragmentList.clear();
|
||||
fragmentList = null;
|
||||
}
|
||||
if (tabTitleList != null) {
|
||||
tabTitleList.clear();
|
||||
tabTitleList = null;
|
||||
}
|
||||
isFragmentInit = null;
|
||||
LogUtils.d(TAG, "===== onDestroy: 主Activity销毁完成 =====");
|
||||
}
|
||||
|
||||
@@ -296,14 +311,15 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化ViewPager与Tab数据(Java7规范,泛型完整声明)
|
||||
* 初始化ViewPager与Tab数据(Java7规范,泛型完整声明),添加懒加载标记
|
||||
* 关键修改:延迟50ms初始化首屏,确保Fragment控件就绪;删除setPrimaryItem冲突逻辑
|
||||
*/
|
||||
private void initViewPagerAndTabs() {
|
||||
LogUtils.d(TAG, "initViewPagerAndTabs: 开始初始化ViewPager数据");
|
||||
fragmentList = new ArrayList<Fragment>();
|
||||
tabTitleList = new ArrayList<String>();
|
||||
|
||||
// 添加Fragment与标题
|
||||
// 添加Fragment实例(仅创建对象,不初始化业务逻辑)
|
||||
fragmentList.add(CallLogFragment.newInstance(0));
|
||||
fragmentList.add(ContactsFragment.newInstance(1));
|
||||
fragmentList.add(LogFragment.newInstance(2));
|
||||
@@ -311,13 +327,57 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
|
||||
tabTitleList.add("联系人");
|
||||
tabTitleList.add("应用日志");
|
||||
|
||||
// 设置适配器
|
||||
MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager(), fragmentList, tabTitleList);
|
||||
// 初始化懒加载标记数组(默认均未初始化)
|
||||
int fragmentCount = fragmentList.size();
|
||||
isFragmentInit = new boolean[fragmentCount];
|
||||
for (int i = 0; i < fragmentCount; i++) {
|
||||
isFragmentInit[i] = false;
|
||||
}
|
||||
|
||||
// 设置自定义适配器(已删除setPrimaryItem,避免初始化冲突)
|
||||
LazyLoadPagerAdapter adapter = new LazyLoadPagerAdapter(getSupportFragmentManager(), fragmentList, tabTitleList);
|
||||
viewPager.setAdapter(adapter);
|
||||
viewPager.setOffscreenPageLimit(2);
|
||||
// 关闭预加载(设为0仅加载当前页,关键)
|
||||
viewPager.setOffscreenPageLimit(0);
|
||||
viewPager.addOnPageChangeListener(this);
|
||||
|
||||
LogUtils.d(TAG, "initViewPagerAndTabs: ViewPager初始化完成,Fragment数量=" + fragmentList.size());
|
||||
// 关键优化:延迟50ms初始化首屏(确保Fragment已完成onCreateView,控件绑定就绪)
|
||||
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
initFragmentByPosition(0);
|
||||
LogUtils.d(TAG, "initViewPagerAndTabs: 延迟初始化首屏Fragment,位置=0");
|
||||
}
|
||||
}, 50);
|
||||
|
||||
LogUtils.d(TAG, "initViewPagerAndTabs: ViewPager初始化完成,等待延迟初始化首屏");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据位置初始化Fragment(调用Fragment的初始化逻辑,避免重复执行)
|
||||
* 优化:添加isAdded判断,确保Fragment已附加到Activity,防止上下文空指针
|
||||
*/
|
||||
private void initFragmentByPosition(int position) {
|
||||
// 校验位置合法性 + 避免重复初始化 + 确保Fragment已附加到Activity
|
||||
if (position < 0 || position >= fragmentList.size() || isFragmentInit[position]) {
|
||||
return;
|
||||
}
|
||||
Fragment targetFragment = fragmentList.get(position);
|
||||
if (targetFragment != null && targetFragment.isAdded()) {
|
||||
// 触发Fragment初始化(调用各Fragment的initData方法)
|
||||
if (targetFragment instanceof CallLogFragment) {
|
||||
((CallLogFragment) targetFragment).initData();
|
||||
} else if (targetFragment instanceof ContactsFragment) {
|
||||
((ContactsFragment) targetFragment).initData();
|
||||
} else if (targetFragment instanceof LogFragment) {
|
||||
((LogFragment) targetFragment).initData();
|
||||
}
|
||||
// 标记为已初始化
|
||||
isFragmentInit[position] = true;
|
||||
LogUtils.d(TAG, "initFragmentByPosition: 初始化Fragment,位置=" + position + ",标题=" + tabTitleList.get(position));
|
||||
} else {
|
||||
LogUtils.w(TAG, "initFragmentByPosition: Fragment未附加到Activity/实例为空,位置=" + position);
|
||||
}
|
||||
}
|
||||
|
||||
// ====================== 10. 菜单相关函数区 ======================
|
||||
@@ -338,7 +398,7 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
// ====================== 11. ViewPager页面回调区 ======================
|
||||
// ====================== 11. ViewPager页面回调区(切换时初始化对应Fragment) ======================
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
|
||||
|
||||
@@ -346,6 +406,8 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
|
||||
public void onPageSelected(int position) {
|
||||
currentPoint = position;
|
||||
LogUtils.d(TAG, "onPageSelected: 页面切换至[" + position + "],标题=" + tabTitleList.get(position));
|
||||
// 切换页面时,初始化当前页Fragment(未初始化过才执行)
|
||||
initFragmentByPosition(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -420,17 +482,17 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
|
||||
|
||||
// ====================== 13. 内部类定义区(Java 7 规范,禁止Lambda) ======================
|
||||
/**
|
||||
* ViewPager适配器(静态内部类减少内存泄漏风险,Java7泛型完整声明)
|
||||
* 自定义懒加载ViewPager适配器(删除setPrimaryItem方法,解决首屏初始化冲突)
|
||||
*/
|
||||
private static class MyPagerAdapter extends FragmentPagerAdapter {
|
||||
private class LazyLoadPagerAdapter extends FragmentPagerAdapter {
|
||||
private final List<Fragment> fragmentList;
|
||||
private final List<String> tabTitleList;
|
||||
|
||||
public MyPagerAdapter(FragmentManager fm, List<Fragment> fragmentList, List<String> tabTitleList) {
|
||||
public LazyLoadPagerAdapter(FragmentManager fm, List<Fragment> fragmentList, List<String> tabTitleList) {
|
||||
super(fm);
|
||||
this.fragmentList = fragmentList;
|
||||
this.tabTitleList = tabTitleList;
|
||||
LogUtils.d(MainActivity.TAG, "MyPagerAdapter: 初始化完成,Fragment数量=" + fragmentList.size());
|
||||
LogUtils.d(MainActivity.TAG, "LazyLoadPagerAdapter: 初始化完成,Fragment数量=" + fragmentList.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -447,6 +509,8 @@ public final class MainActivity extends WinBollActivity implements IWinBoLLActiv
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return tabTitleList.get(position);
|
||||
}
|
||||
|
||||
// 【已删除】移除setPrimaryItem方法,避免与手动初始化+onPageSelected回调冲突
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.util.List;
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/02/20 12:57:00
|
||||
* @Describe 通话记录区域视图
|
||||
* @Describe 通话记录区域视图(支持懒加载,仅切换到当前页才加载数据)
|
||||
*/
|
||||
public class CallLogFragment extends Fragment {
|
||||
|
||||
@@ -51,6 +51,8 @@ public class CallLogFragment extends Fragment {
|
||||
|
||||
// ====================== 业务逻辑成员区 ======================
|
||||
private Handler mHandler;
|
||||
// 懒加载标记:记录当前Fragment是否已初始化数据(避免重复加载)
|
||||
private boolean isDataInited = false;
|
||||
|
||||
// ====================== 单例与实例化函数区 ======================
|
||||
CallLogFragment() {
|
||||
@@ -99,34 +101,28 @@ public class CallLogFragment extends Fragment {
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
LogUtils.d(TAG, "onViewCreated: 视图创建完成,初始化控件");
|
||||
// 初始化RecyclerView
|
||||
LogUtils.d(TAG, "onViewCreated: 视图创建完成,仅初始化控件(不加载数据)");
|
||||
// 初始化RecyclerView(仅绑定控件、设置布局管理器,不设置数据/发起请求)
|
||||
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
// 初始化适配器(传入空列表,后续懒加载时更新数据)
|
||||
callLogAdapter = new CallLogAdapter(getContext(), callLogList);
|
||||
recyclerView.setAdapter(callLogAdapter);
|
||||
LogUtils.d(TAG, "onViewCreated: RecyclerView初始化完成");
|
||||
|
||||
// 权限检查与数据加载
|
||||
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
|
||||
LogUtils.w(TAG, "onViewCreated: 读取通话记录权限未授予,发起权限申请");
|
||||
ActivityCompat.requestPermissions(requireActivity(), new String[]{Manifest.permission.READ_CALL_LOG}, REQUEST_READ_CALL_LOG);
|
||||
} else {
|
||||
LogUtils.d(TAG, "onViewCreated: 权限已授予,发送更新消息");
|
||||
mHandler.sendEmptyMessage(MSG_UPDATE);
|
||||
}
|
||||
LogUtils.d(TAG, "onViewCreated: RecyclerView控件初始化完成(未加载数据)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
LogUtils.d(TAG, "onResume: Fragment进入前台,刷新数据");
|
||||
if (callLogAdapter != null) {
|
||||
LogUtils.d(TAG, "onResume: Fragment进入前台");
|
||||
// 已初始化过数据 → 仅刷新(避免重复初始化,优化性能)
|
||||
if (isDataInited && callLogAdapter != null) {
|
||||
LogUtils.d(TAG, "onResume: 数据已初始化,仅刷新列表");
|
||||
callLogAdapter.relaodContacts();
|
||||
LogUtils.d(TAG, "onResume: 适配器数据重新加载");
|
||||
readCallLog(); // 刷新最新通话记录
|
||||
LogUtils.d(TAG, "onResume: 通话记录数据刷新完成");
|
||||
}
|
||||
readCallLog();
|
||||
LogUtils.d(TAG, "onResume: 通话记录数据刷新完成");
|
||||
// 未初始化 → 不操作(等待MainActivity调用initData触发初始化)
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,7 +133,15 @@ public class CallLogFragment extends Fragment {
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
LogUtils.d(TAG, "onDestroy: Handler消息已清空");
|
||||
}
|
||||
// 释放资源,避免内存泄漏
|
||||
if (callLogList != null) {
|
||||
callLogList.clear();
|
||||
callLogList = null;
|
||||
}
|
||||
callLogAdapter = null;
|
||||
recyclerView = null;
|
||||
_CallLogFragment = null;
|
||||
isDataInited = false;
|
||||
LogUtils.d(TAG, "onDestroy: Fragment销毁完成");
|
||||
}
|
||||
|
||||
@@ -148,26 +152,52 @@ public class CallLogFragment extends Fragment {
|
||||
LogUtils.d(TAG, "onRequestPermissionsResult: 权限请求回调,requestCode=" + requestCode);
|
||||
if (requestCode == REQUEST_READ_CALL_LOG) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
LogUtils.d(TAG, "onRequestPermissionsResult: 通话记录权限授予成功,发送更新消息");
|
||||
LogUtils.d(TAG, "onRequestPermissionsResult: 通话记录权限授予成功,开始加载数据");
|
||||
mHandler.sendEmptyMessage(MSG_UPDATE);
|
||||
} else {
|
||||
LogUtils.e(TAG, "onRequestPermissionsResult: 通话记录权限被拒绝");
|
||||
LogUtils.e(TAG, "onRequestPermissionsResult: 通话记录权限被拒绝,无法加载数据");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ====================== 懒加载核心方法(供MainActivity调用) ======================
|
||||
public void initData() {
|
||||
// 避免重复初始化(双重防护:标记+判断)
|
||||
if (isDataInited || getContext() == null) {
|
||||
LogUtils.d(TAG, "initData: 数据已初始化/上下文为空,跳过");
|
||||
return;
|
||||
}
|
||||
LogUtils.d(TAG, "initData: 开始懒加载初始化通话记录数据");
|
||||
// 权限检查与数据加载(原onViewCreated中的核心逻辑迁移至此)
|
||||
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
|
||||
LogUtils.w(TAG, "initData: 读取通话记录权限未授予,发起权限申请");
|
||||
ActivityCompat.requestPermissions(requireActivity(), new String[]{Manifest.permission.READ_CALL_LOG}, REQUEST_READ_CALL_LOG);
|
||||
} else {
|
||||
LogUtils.d(TAG, "initData: 权限已授予,发送更新消息加载数据");
|
||||
mHandler.sendEmptyMessage(MSG_UPDATE);
|
||||
}
|
||||
// 标记为已初始化(后续仅刷新,不重复初始化)
|
||||
isDataInited = true;
|
||||
LogUtils.d(TAG, "initData: 懒加载初始化流程完成");
|
||||
}
|
||||
|
||||
// ====================== 业务核心函数区 ======================
|
||||
private void readCallLog() {
|
||||
LogUtils.d(TAG, "readCallLog: 开始读取系统通话记录");
|
||||
// 避免空指针(懒加载场景下,控件可能未初始化完成)
|
||||
if (callLogList == null || callLogAdapter == null || getContext() == null) {
|
||||
LogUtils.w(TAG, "readCallLog: 控件/列表为空,跳过读取");
|
||||
return;
|
||||
}
|
||||
callLogList.clear();
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = requireContext().getContentResolver().query(
|
||||
CallLog.Calls.CONTENT_URI,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
CallLog.Calls.DATE + " DESC"
|
||||
CallLog.Calls.CONTENT_URI,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
CallLog.Calls.DATE + " DESC"
|
||||
);
|
||||
if (cursor != null) {
|
||||
LogUtils.d(TAG, "readCallLog: 成功获取通话记录游标,数据条数=" + cursor.getCount());
|
||||
@@ -211,7 +241,9 @@ public class CallLogFragment extends Fragment {
|
||||
// ====================== 外部调用函数区 ======================
|
||||
public void triggerUpdate() {
|
||||
LogUtils.d(TAG, "triggerUpdate: 外部触发通话记录更新");
|
||||
mHandler.sendEmptyMessage(MSG_UPDATE);
|
||||
if (isDataInited) { // 已初始化才触发更新(避免未加载时调用)
|
||||
mHandler.sendEmptyMessage(MSG_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateCallLogFragment() {
|
||||
|
||||
@@ -15,29 +15,26 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import cc.winboll.studio.contacts.R;
|
||||
import cc.winboll.studio.contacts.adapters.ContactAdapter;
|
||||
import cc.winboll.studio.contacts.model.ContactModel;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.ToastUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/08/30 14:32
|
||||
* @Describe 联系人区域视图
|
||||
* @Describe 联系人区域视图(支持懒加载,仅切换到当前页才加载数据)
|
||||
*/
|
||||
public class ContactsFragment extends Fragment {
|
||||
|
||||
@@ -54,8 +51,9 @@ public class ContactsFragment extends Fragment {
|
||||
|
||||
// ====================== 页面参数区 ======================
|
||||
private int mPage;
|
||||
private boolean isViewInitialized = false; // 视图初始化标记
|
||||
private boolean isDataLoaded = false; // 数据加载标记
|
||||
private boolean isViewInitialized = false; // 视图初始化标记(控件绑定完成)
|
||||
private boolean isDataLoaded = false; // 数据加载标记(数据+功能初始化完成)
|
||||
private boolean isLazyInitCompleted = false; // 懒加载总标记(供MainActivity判断)
|
||||
|
||||
// ====================== UI控件区 ======================
|
||||
private RecyclerView recyclerView;
|
||||
@@ -103,32 +101,38 @@ public class ContactsFragment extends Fragment {
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
LogUtils.d(TAG, "onViewCreated: 开始初始化UI控件");
|
||||
// 初始化RecyclerView
|
||||
LogUtils.d(TAG, "onViewCreated: 开始初始化UI控件(仅绑定,不加载数据/功能)");
|
||||
// 初始化RecyclerView(仅绑定控件、设适配器,隐藏列表)
|
||||
recyclerView = (RecyclerView) view.findViewById(R.id.contacts_recycler_view);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
contactAdapter = new ContactAdapter(getActivity(), contactList);
|
||||
recyclerView.setAdapter(contactAdapter);
|
||||
recyclerView.setVisibility(View.GONE); // 初始隐藏列表
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
|
||||
// 绑定搜索框和拨号按钮
|
||||
// 绑定搜索框和拨号按钮(仅赋值,不显示、不绑定事件)
|
||||
searchEditText = (EditText) view.findViewById(R.id.search_edit_text);
|
||||
btnDial = (Button) view.findViewById(R.id.btn_dial);
|
||||
searchEditText.setVisibility(View.GONE);
|
||||
btnDial.setVisibility(View.GONE);
|
||||
LogUtils.d(TAG, "onViewCreated: UI控件初始化完成");
|
||||
|
||||
// 标记视图控件绑定完成
|
||||
isViewInitialized = true;
|
||||
LogUtils.d(TAG, "onViewCreated: UI控件初始化完成(未加载数据/功能)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
LogUtils.d(TAG, "onResume: Fragment进入前台");
|
||||
if (!isViewInitialized) {
|
||||
initSearchAndDial();
|
||||
checkContactPermission();
|
||||
isViewInitialized = true;
|
||||
LogUtils.d(TAG, "onResume: 首次进入,完成视图和权限初始化");
|
||||
// 已完成懒加载 → 仅恢复缓存数据(切回页面时刷新)
|
||||
if (isLazyInitCompleted && isDataLoaded) {
|
||||
LogUtils.d(TAG, "onResume: 懒加载已完成,恢复缓存数据");
|
||||
contactList.clear();
|
||||
contactList.addAll(sCachedFilteredList);
|
||||
contactAdapter.notifyDataSetChanged();
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
// 未完成懒加载 → 不操作(等待MainActivity调用initData触发)
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,14 +141,28 @@ public class ContactsFragment extends Fragment {
|
||||
LogUtils.d(TAG, "onDestroy: Fragment开始销毁");
|
||||
executor.shutdown(); // 关闭线程池
|
||||
mainHandler.removeCallbacksAndMessages(null); // 清空Handler任务
|
||||
LogUtils.d(TAG, "onDestroy: 异步工具资源已释放");
|
||||
// 释放本地数据引用(保留静态缓存,全局复用)
|
||||
if (contactList != null) {
|
||||
contactList.clear();
|
||||
contactList = null;
|
||||
}
|
||||
if (originalContactList != null) {
|
||||
originalContactList.clear();
|
||||
originalContactList = null;
|
||||
}
|
||||
// 重置标记
|
||||
isViewInitialized = false;
|
||||
isDataLoaded = false;
|
||||
isLazyInitCompleted = false;
|
||||
LogUtils.d(TAG, "onDestroy: 异步工具+本地资源已释放");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHiddenChanged(boolean hidden) {
|
||||
super.onHiddenChanged(hidden);
|
||||
LogUtils.d(TAG, "onHiddenChanged: Fragment隐藏状态变更,hidden=" + hidden);
|
||||
if (!hidden && isDataLoaded) {
|
||||
// 已完成懒加载+显示状态 → 恢复缓存数据(兼容Tab切换场景)
|
||||
if (!hidden && isLazyInitCompleted && isDataLoaded) {
|
||||
contactList.clear();
|
||||
contactList.addAll(sCachedFilteredList);
|
||||
contactAdapter.notifyDataSetChanged();
|
||||
@@ -177,10 +195,29 @@ public class ContactsFragment extends Fragment {
|
||||
LogUtils.e(TAG, "onRequestPermissionsResult: 联系人权限被拒绝");
|
||||
ToastUtils.show("请授予联系人权限以查看联系人列表");
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
// 权限拒绝也标记懒加载完成(避免重复触发)
|
||||
isLazyInitCompleted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ====================== 懒加载核心方法(供MainActivity调用) ======================
|
||||
public void initData() {
|
||||
// 双重防护:避免重复初始化(标记+视图就绪判断)
|
||||
if (isLazyInitCompleted || !isViewInitialized || getContext() == null) {
|
||||
LogUtils.d(TAG, "initData: 懒加载已完成/视图未就绪,跳过");
|
||||
return;
|
||||
}
|
||||
LogUtils.d(TAG, "initData: 开始懒加载初始化(功能+数据)");
|
||||
// 1. 初始化搜索、拨号功能(原onResume首次进入逻辑迁移至此)
|
||||
initSearchAndDial();
|
||||
// 2. 检查权限+加载数据(原onResume首次进入逻辑迁移至此)
|
||||
checkContactPermission();
|
||||
// 标记懒加载总流程完成(无论权限是否授予,仅执行一次)
|
||||
isLazyInitCompleted = true;
|
||||
LogUtils.d(TAG, "initData: 懒加载初始化流程启动完成");
|
||||
}
|
||||
|
||||
// ====================== UI功能初始化区 ======================
|
||||
private void initSearchAndDial() {
|
||||
LogUtils.d(TAG, "initSearchAndDial: 初始化搜索和拨号功能");
|
||||
@@ -217,7 +254,7 @@ public class ContactsFragment extends Fragment {
|
||||
|
||||
// ====================== 数据加载与处理区 ======================
|
||||
private void loadContacts() {
|
||||
// 优先使用缓存数据
|
||||
// 优先使用缓存数据(保留原有缓存逻辑,提升性能)
|
||||
if (!sCachedOriginalList.isEmpty() && !sCachedFilteredList.isEmpty()) {
|
||||
LogUtils.d(TAG, "loadContacts: 存在缓存数据,直接复用");
|
||||
originalContactList.clear();
|
||||
@@ -230,7 +267,7 @@ public class ContactsFragment extends Fragment {
|
||||
return;
|
||||
}
|
||||
|
||||
// 无缓存时异步加载
|
||||
// 无缓存时异步加载(保留原有异步逻辑,避免主线程阻塞)
|
||||
if (!isDataLoaded) {
|
||||
LogUtils.d(TAG, "loadContacts: 无缓存,异步读取联系人数据");
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
@@ -270,14 +307,14 @@ public class ContactsFragment extends Fragment {
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = requireContext().getContentResolver().query(
|
||||
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
|
||||
new String[]{
|
||||
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
|
||||
ContactsContract.CommonDataKinds.Phone.NUMBER
|
||||
},
|
||||
null,
|
||||
null,
|
||||
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC"
|
||||
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
|
||||
new String[]{
|
||||
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
|
||||
ContactsContract.CommonDataKinds.Phone.NUMBER
|
||||
},
|
||||
null,
|
||||
null,
|
||||
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC"
|
||||
);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
|
||||
@@ -4,11 +4,9 @@ import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import cc.winboll.studio.contacts.R;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.LogView;
|
||||
@@ -16,7 +14,7 @@ import cc.winboll.studio.libappbase.LogView;
|
||||
/**
|
||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||
* @Date 2025/02/20 12:58:15
|
||||
* @Describe 应用日志区域视图
|
||||
* @Describe 应用日志区域视图(支持懒加载,仅切换到当前页才启动日志)
|
||||
*/
|
||||
public class LogFragment extends Fragment {
|
||||
|
||||
@@ -30,6 +28,11 @@ public class LogFragment extends Fragment {
|
||||
// ====================== UI控件区 ======================
|
||||
private LogView mLogView;
|
||||
|
||||
// ====================== 懒加载标记区 ======================
|
||||
private boolean isViewInitialized = false; // 视图控件绑定完成标记
|
||||
private boolean isLazyInitCompleted = false; // 懒加载总流程完成标记
|
||||
private boolean isLogViewStarted = false; // LogView启动状态标记
|
||||
|
||||
// ====================== 实例化函数区 ======================
|
||||
public static LogFragment newInstance(int page) {
|
||||
LogUtils.d(TAG, "newInstance: 创建日志Fragment实例,页码=" + page);
|
||||
@@ -58,10 +61,11 @@ public class LogFragment extends Fragment {
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
LogUtils.d(TAG, "onCreateView: 加载Fragment布局");
|
||||
View view = inflater.inflate(R.layout.fragment_log, container, false);
|
||||
// Java7 适配:添加强制类型转换
|
||||
// Java7 适配:添加强制类型转换,仅初始化LogView控件(不启动)
|
||||
mLogView = (LogView) view.findViewById(R.id.logview);
|
||||
mLogView.start();
|
||||
LogUtils.d(TAG, "onCreateView: LogView已初始化并启动");
|
||||
LogUtils.d(TAG, "onCreateView: LogView控件初始化完成(未启动)");
|
||||
// 标记视图控件绑定完成
|
||||
isViewInitialized = true;
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -69,12 +73,13 @@ public class LogFragment extends Fragment {
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
LogUtils.d(TAG, "onResume: Fragment进入前台");
|
||||
if (mLogView != null) {
|
||||
// 已完成懒加载 → 仅重启LogView(切回页面时恢复日志显示)
|
||||
if (isLazyInitCompleted && mLogView != null && !isLogViewStarted) {
|
||||
mLogView.start();
|
||||
LogUtils.d(TAG, "onResume: LogView已重启");
|
||||
} else {
|
||||
LogUtils.w(TAG, "onResume: LogView实例为空,跳过启动");
|
||||
isLogViewStarted = true;
|
||||
LogUtils.d(TAG, "onResume: LogView已重启,恢复日志显示");
|
||||
}
|
||||
// 未完成懒加载 → 不操作(等待MainActivity调用initData触发)
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,11 +87,32 @@ public class LogFragment extends Fragment {
|
||||
super.onDestroy();
|
||||
LogUtils.d(TAG, "onDestroy: Fragment开始销毁");
|
||||
if (mLogView != null) {
|
||||
// 若LogView有停止方法,建议在此处调用,避免资源泄漏
|
||||
// mLogView.stop();
|
||||
LogUtils.d(TAG, "onDestroy: LogView资源已处理");
|
||||
// 若LogView有停止方法,必须调用(避免后台持续占用资源,根据实际API调整)
|
||||
// mLogView.stop(); // 关键:释放LogView资源,防止内存泄漏
|
||||
LogUtils.d(TAG, "onDestroy: LogView资源已释放");
|
||||
}
|
||||
// 重置所有标记,避免重建时状态异常
|
||||
mLogView = null;
|
||||
isViewInitialized = false;
|
||||
isLazyInitCompleted = false;
|
||||
isLogViewStarted = false;
|
||||
LogUtils.d(TAG, "onDestroy: Fragment销毁完成");
|
||||
}
|
||||
|
||||
// ====================== 懒加载核心方法(供MainActivity调用) ======================
|
||||
public void initData() {
|
||||
// 双重防护:避免重复初始化(标记+视图就绪+控件非空)
|
||||
if (isLazyInitCompleted || !isViewInitialized || mLogView == null || getContext() == null) {
|
||||
LogUtils.d(TAG, "initData: 懒加载已完成/视图未就绪,跳过");
|
||||
return;
|
||||
}
|
||||
LogUtils.d(TAG, "initData: 开始懒加载初始化,启动LogView");
|
||||
// 核心:启动LogView(原onCreateView中的start逻辑迁移至此)
|
||||
mLogView.start();
|
||||
isLogViewStarted = true;
|
||||
// 标记懒加载总流程完成(仅执行一次)
|
||||
isLazyInitCompleted = true;
|
||||
LogUtils.d(TAG, "initData: 懒加载初始化完成,LogView正常启动");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user