LiveData原理解析和仿写一个LiveDataBus

2024-02-17 17:08

本文主要是介绍LiveData原理解析和仿写一个LiveDataBus,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引入LiveData:

implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0"

学习内容:

//这个实际上还是继承了LiveData
public class MutableLiveData<T> extends LiveData<T> {@Overridepublic void postValue(T value) {super.postValue(value);}@Overridepublic void setValue(T value) {super.setValue(value);}
}

开始使用

//初始化
MutableLiveData<String> liveData = new MutableLiveData<>();
//有两种发送值的方式
//第一种
liveData.setValue("123");
//第二种
liveData.postValue("456");

接下来从源码的角度来分析这两个方法的区别。
liveData.postValue

	private final Runnable mPostValueRunnable = new Runnable() {@Overridepublic void run() {Object newValue;synchronized (mDataLock) {newValue = mPendingData;mPendingData = NOT_SET;}//noinspection unchecked//postValue切换到主线程,最终还是调用了setValue()setValue((T) newValue);}};protected void postValue(T value) {boolean postTask;synchronized (mDataLock) {postTask = mPendingData == NOT_SET;mPendingData = value;}if (!postTask) {return;}//可以看到这里我们将赋值的操作切换到主线程,然后再执行。ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);}

所以liveData.postValue可以再任意的线程调用,因为最终会切换到主线程。
liveData.setValue

 @MainThreadprotected void setValue(T value) {//断言的方式判断当前是不是主线程assertMainThread("setValue");//每次设置值的时候都会+1mVersion++;mData = value;//分发更新的值dispatchingValue(null);}

所以liveData.setValue只能再主线程中调用。
然后当我们调用了setValue()之后,接着看dispatchingValue这个方法

public abstract class LiveData<T> {static final int START_VERSION = -1;//观察者的 mapprivate SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =new SafeIterableMap<>();private int mVersion = START_VERSION;
......void dispatchingValue(@Nullable ObserverWrapper initiator) {if (mDispatchingValue) {mDispatchInvalidated = true;return;}mDispatchingValue = true;do {mDispatchInvalidated = false;if (initiator != null) {considerNotify(initiator);initiator = null;} else {//因为initiator = null 所以执行这个方法 遍历每个observerfor (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {//执行这个方法considerNotify(iterator.next().getValue());if (mDispatchInvalidated) {break;}}}} while (mDispatchInvalidated);mDispatchingValue = false;}//最后调用观察者的回调的方法private void considerNotify(ObserverWrapper observer) {if (!observer.mActive) {return;}// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.//// we still first check observer.active to keep it as the entrance for events. So even if// the observer moved to an active state, if we've not received that event, we better not// notify for a more predictable notification order.if (!observer.shouldBeActive()) {observer.activeStateChanged(false);return;}//这个判断非常重要哦//刚开始的时候这两个值都为-1//所以第一次进来就会return//但setValue()执行后,mVersion就+1了,所以就不会return了//这样保证了观察者的回调方法不会因为生命周期的多次回调而调用多次//这个判断也是我们下文仿写LiveDataBus的重要判断条件if (observer.mLastVersion >= mVersion) {return;}observer.mLastVersion = mVersion;//noinspection unchecked//调用观察者的回调方法,进行更新的操作。observer.mObserver.onChanged((T) mData);}//生命周期改变时会回调
//GenericLifecycleObserver.onStateChanged方法(是感知到生命周期的重要原因)
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {@NonNullfinal LifecycleOwner mOwner;LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {super(observer);mOwner = owner;}@Overrideboolean shouldBeActive() {return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);}//生命周期改变时会回调这个方法@Overridepublic void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {removeObserver(mObserver);return;}//执行父类里的方法activeStateChanged(shouldBeActive());}@Overrideboolean isAttachedTo(LifecycleOwner owner) {return mOwner == owner;}@Overridevoid detachObserver() {mOwner.getLifecycle().removeObserver(this);}}private abstract class ObserverWrapper {final Observer<? super T> mObserver;boolean mActive;int mLastVersion = START_VERSION;ObserverWrapper(Observer<? super T> observer) {mObserver = observer;}abstract boolean shouldBeActive();boolean isAttachedTo(LifecycleOwner owner) {return false;}void detachObserver() {}void activeStateChanged(boolean newActive) {if (newActive == mActive) {return;}// immediately set active state, so we'd never dispatch anything to inactive// ownermActive = newActive;boolean wasInactive = LiveData.this.mActiveCount == 0;LiveData.this.mActiveCount += mActive ? 1 : -1;if (wasInactive && mActive) {onActive();}if (LiveData.this.mActiveCount == 0 && !mActive) {onInactive();}if (mActive) {//分发值 需要更新dispatchingValue(this);}}}
}

到这里观察的回调在哪里调用了,我们就搞清了,我们暂时先不要管onStateChanged再生命周期为什么回调,下文会介绍的不要急。
接下来就是设置观察者了。

liveData.observe(this, new Observer<String>() {@Overridepublic void onChanged(String s) {//在这里处理你自己的逻辑}});

我们就来看这个方法内部是怎么执行的。

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {assertMainThread("observe");//判断当前活动是否被销毁,被销毁直接返回,不注册if (owner.getLifecycle().getCurrentState() == DESTROYED) {// ignorereturn;}LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);if (existing != null && !existing.isAttachedTo(owner)) {throw new IllegalArgumentException("Cannot add the same observer"+ " with different lifecycles");}if (existing != null) {return;}//所以这里就是等于在activity里写如下的代码//AppCompatActivity.getLifecycle().addObserver(wrapper);//这跟之前我们监听activity生周期的方法一样呢//这就是LiveData为什么能感知生命周期的原因owner.getLifecycle().addObserver(wrapper);}

可以看到这个owner,有的小伙会问,欸?为什么是这个形参的类型是LifecycleOwner这是因为我们的AppCompatActivity继承了FragmentActivity继承了ComponentActivity的实现了LifecycleOwner。

public class AppCompatActivity extends FragmentActivity implements AppCompatCallback,TaskStackBuilder.SupportParentable, ActionBarDrawerToggle.DelegateProvider {......
}public class FragmentActivity extends ComponentActivity implementsViewModelStoreOwner,ActivityCompat.OnRequestPermissionsResultCallback,ActivityCompat.RequestPermissionsRequestCodeValidator {
}public class ComponentActivity extends Activityimplements LifecycleOwner, KeyEventDispatcher.Component {
}

现在我们再来看一种代码

MutableLiveData<String> liveData = new MutableLiveData<>();
liveData.setValue("123");
liveData.observe(this, new Observer<String>() {@Overridepublic void onChanged(String s) {}
});

这段代码注意 我们是先发送值,然后注册监听者,大家认为我们可以在onChanged回调时接收到“123”吗?答案是肯定的,但这有点不符合常理了,毕竟我们先发送值,但这时候还没有注册事件监听者,后来才注册的事件监听者,也能收到,这就有点奇怪了,我们来看一下LiveData是怎么实现的。

这就要牵扯到下面这段代码了

class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {@NonNullfinal LifecycleOwner mOwner;LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {super(observer);mOwner = owner;}@Overrideboolean shouldBeActive() {return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);}@Override//每次生命周期变化都会调用public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {removeObserver(mObserver);return;}//调用父类里的方法activeStateChanged(shouldBeActive());}.....
}
private abstract class ObserverWrapper {final Observer<? super T> mObserver;boolean mActive;int mLastVersion = START_VERSION;.......void activeStateChanged(boolean newActive) {if (newActive == mActive) {return;}// immediately set active state, so we'd never dispatch anything to inactive// ownermActive = newActive;boolean wasInactive = LiveData.this.mActiveCount == 0;LiveData.this.mActiveCount += mActive ? 1 : -1;if (wasInactive && mActive) {onActive();}if (LiveData.this.mActiveCount == 0 && !mActive) {onInactive();}if (mActive) {//调用更新的值分发dispatchingValue(this);}}}.....
}

这段逻辑,相信从上面看到下面的小伙伴都有印象,所以弄清楚onStateChanged为什么在生命周期改变时会被调用。
owner.getLifecycle().addObserver(wrapper);这句话就是我们观察者被注册到监听者的方法。

public class FragmentActivity extends ComponentActivity implementsViewModelStoreOwner,ActivityCompat.OnRequestPermissionsResultCallback,ActivityCompat.RequestPermissionsRequestCodeValidator {.....@Overridepublic Lifecycle getLifecycle() {return super.getLifecycle();}......
}
public class ComponentActivity extends Activityimplements LifecycleOwner, KeyEventDispatcher.Component {private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);@Overridepublic Lifecycle getLifecycle() {return mLifecycleRegistry;}}

所以当我们getLifecycle().addObserver()得到的对象是LifecycleRegistry.addObserver()

	@Overridepublic void addObserver(@NonNull LifecycleObserver observer) {//获取当前activity处在那个生命周期//DESTROYED:0  INITIALIZED:1State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;//下面这两行代码跟LiveData.observe()里的两行代码差不多的ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);if (previous != null) {return;}LifecycleOwner lifecycleOwner = mLifecycleOwner.get();if (lifecycleOwner == null) {// it is null we should be destroyed. Fallback quicklyreturn;}boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;State targetState = calculateTargetState(observer);mAddingObserverCounter++;while ((statefulObserver.mState.compareTo(targetState) < 0&& mObserverMap.contains(observer))) {pushParentState(statefulObserver.mState);statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));popParentState();// mState / subling may have been changed recalculatetargetState = calculateTargetState(observer);}if (!isReentrance) {// we do sync only on the top level.//到这了sync();}mAddingObserverCounter--;}private void sync() {LifecycleOwner lifecycleOwner = mLifecycleOwner.get();if (lifecycleOwner == null) {Log.w(LOG_TAG, "LifecycleOwner is garbage collected, you shouldn't try dispatch "+ "new events from it.");return;}while (!isSynced()) {mNewEventOccurred = false;// no need to check eldest for nullability, because isSynced does it for us.//if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {backwardPass(lifecycleOwner);}Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();if (!mNewEventOccurred && newest != null&& mState.compareTo(newest.getValue().mState) > 0) {forwardPass(lifecycleOwner);}}mNewEventOccurred = false;}private void forwardPass(LifecycleOwner lifecycleOwner) {Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =mObserverMap.iteratorWithAdditions();//从观察者map 迭代所有的观察者while (ascendingIterator.hasNext() && !mNewEventOccurred) {Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();ObserverWithState observer = entry.getValue();while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred&& mObserverMap.contains(entry.getKey()))) {pushParentState(observer.mState);//然后就调用这个方法observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));popParentState();}}}private void backwardPass(LifecycleOwner lifecycleOwner) {Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =mObserverMap.descendingIterator();while (descendingIterator.hasNext() && !mNewEventOccurred) {Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();ObserverWithState observer = entry.getValue();while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred&& mObserverMap.contains(entry.getKey()))) {Event event = downEvent(observer.mState);pushParentState(getStateAfter(event));observer.dispatchEvent(lifecycleOwner, event);popParentState();}}}static class ObserverWithState {State mState;GenericLifecycleObserver mLifecycleObserver;ObserverWithState(LifecycleObserver observer, State initialState) {mLifecycleObserver = Lifecycling.getCallback(observer);mState = initialState;}void dispatchEvent(LifecycleOwner owner, Event event) {State newState = getStateAfter(event);mState = min(mState, newState);//然后到这儿就会回调我们在LiveData里的LifecycleBoundObserver的onStateChanged方法mLifecycleObserver.onStateChanged(owner, event);mState = newState;}}

所以sync()方法最终会导致我们的事件回调(记下这个方法名)
然后我们继续

public class ComponentActivity extends Activityimplements LifecycleOwner, KeyEventDispatcher.Component {......@Override@SuppressWarnings("RestrictedApi")protected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);//看到这里,我们把自己传了进去ReportFragment.injectIfNeededIn(this);}......
}
public class ReportFragment extends Fragment {private static final String REPORT_FRAGMENT_TAG = "androidx.lifecycle"+ ".LifecycleDispatcher.report_fragment_tag";public static void injectIfNeededIn(Activity activity) {// ProcessLifecycleOwner should always correctly work and some activities may not extend// FragmentActivity from support lib, so we use framework fragments for activities//这里我们看到我们启动了一个ReportFragmentandroid.app.FragmentManager manager = activity.getFragmentManager();if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();// Hopefully, we are the first to make a transaction.manager.executePendingTransactions();}}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);dispatchCreate(mProcessListener);dispatch(Lifecycle.Event.ON_CREATE);}@Overridepublic void onStart() {super.onStart();dispatchStart(mProcessListener);dispatch(Lifecycle.Event.ON_START);}@Overridepublic void onResume() {super.onResume();dispatchResume(mProcessListener);dispatch(Lifecycle.Event.ON_RESUME);}private void dispatch(Lifecycle.Event event) {Activity activity = getActivity();if (activity instanceof LifecycleRegistryOwner) {((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);return;}if (activity instanceof LifecycleOwner) {Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();if (lifecycle instanceof LifecycleRegistry) {((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);}}}
.......
}

我们可以看到在ReportFragment的生命周期中都有同一个方法dispatch(),而且最终都会调用getLifecycle().handleLifecycleEvent(event)

 public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {State next = getStateAfter(event);moveToState(next);}private void moveToState(State next) {if (mState == next) {return;}mState = next;if (mHandlingEvent || mAddingObserverCounter != 0) {mNewEventOccurred = true;// we will figure out what to do on upper level.return;}mHandlingEvent = true;//看这个sync(),上面我们就见过这个方法,所以就可以说通了sync();mHandlingEvent = false;}

正是通过这个handleLifecycleEvent调用了sync然后再调用了dispatchEvent然后调用了mLifecycleObserver.onStateChanged

但是我们LiveData一般都不是用来监听生命周期的,都是用来组件间通信的所以我就来仿照LiveDataBus写一个自己的组件通信,但是我们有的时候不需要粘性事件(未注册的监听者不因该监听到注册前所发送过的事件),所以我们需要自己实现一个可以控制黏性的事件通知者。

//黏性事件
public class MyLiveDataBus {private static MyLiveDataBus instance = new MyLiveDataBus();private Map<String, MyMutableLiveData<Object>> liveDataMap;public static MyLiveDataBus getInstance(){return instance;}private MyLiveDataBus(){liveDataMap = new HashMap<>();}public synchronized<T> MyMutableLiveData<T> with(String key,Class<T> clazz){if(!liveDataMap.containsKey(key)){liveDataMap.put(key,new MyMutableLiveData<Object>());}return (MyMutableLiveData<T>) liveDataMap.get(key);}private static class MyMutableLiveData<T> extends MutableLiveData<T> {private boolean isSticky = false;public void observe(@NonNull LifecycleOwner owner, boolean isSticky , @NonNull Observer<? super T> observer) {this.isSticky = isSticky ;observe(owner,observer);}@Overridepublic void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {super.observe(owner, observer);try {if(!isSticky ){hook((Observer<T>) observer);}} catch (Exception e) {e.printStackTrace();}}//让mLastVersion和mVersion相等,这样可以在注册监听的时候就不会回调onStateChanged了private void hook(Observer<T> observer) throws Exception {Class<LiveData> liveDataClass = LiveData.class;Field mObserversField = liveDataClass.getDeclaredField("mObservers");mObserversField.setAccessible(true);Object mObservers = mObserversField.get(this);Method get = mObservers.getClass().getDeclaredMethod("get", Object.class);get.setAccessible(true);Object invokeEntry = get.invoke(mObservers, observer);Object observerWrapper = null;if(invokeEntry!=null && invokeEntry instanceof Map.Entry){observerWrapper = ((Map.Entry)invokeEntry).getValue();}if(observerWrapper == null){throw new NullPointerException("ObserverWrapper不能为空");}Class<?> superclass = observerWrapper.getClass().getSuperclass();Field mLastVersionField = superclass.getDeclaredField("mLastVersion");mLastVersionField.setAccessible(true);Field mVersionField = liveDataClass.getDeclaredField("mVersion");mVersionField.setAccessible(true);Object o = mVersionField.get(this);mLastVersionField.set(observerWrapper,o);}}
}

在Activity中

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MutableLiveData<String> liveData = MyLiveDataBus.getInstance().with("key",String.class);liveData.postValue("123");}}public class TwoActivity extends AppCompatActivity {LiveDataBus2.BusMutableLiveData<String> liveData;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);liveData = LiveDataBus2.getInstance().with("code", String.class);liveData.observe(TwoActivity.this,false, new Observer<String>() {@Overridepublic void onChanged(String s) {Log.e("!!!!!!!!",s);}});}}

这样我们就可以实现MainActivity组件和TwoActivity组件之间的通信了,可以不在使用Intent(大小限制)了。

追记:
LiveData当我们继承自Activity就会报错(之前的都是继承了AppCompatActivity)

public class MainActivity extends Activity {
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MyLiveDataBus.MyMutableLiveData<String> liveData = MyLiveDataBus.getInstance().with("key",String.class);//这个observe就会报错 因为继承了ActivityliveData.observe(this, new Observer<String>() {@Overridepublic void onChanged(String s) {}});liveData.setValue("123");}
}

那我们需要怎么修改呢

public class MainActivity extends Activity {LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);@SuppressLint("RestrictedApi")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ReportFragment.injectIfNeededIn(this);MyLiveDataBus.MyMutableLiveData<String> liveData = MyLiveDataBus.getInstance().with("key",String.class);liveData.observe(this, new Observer<String>() {@Overridepublic void onChanged(String s) {}});liveData.setValue("123");}@NonNull@Overridepublic Lifecycle getLifecycle() {return lifecycleRegistry;}}}

这篇关于LiveData原理解析和仿写一个LiveDataBus的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/718454

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

ShardingProxy读写分离之原理、配置与实践过程

《ShardingProxy读写分离之原理、配置与实践过程》ShardingProxy是ApacheShardingSphere的数据库中间件,通过三层架构实现读写分离,解决高并发场景下数据库性能瓶... 目录一、ShardingProxy技术定位与读写分离核心价值1.1 技术定位1.2 读写分离核心价值二

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

深入浅出Spring中的@Autowired自动注入的工作原理及实践应用

《深入浅出Spring中的@Autowired自动注入的工作原理及实践应用》在Spring框架的学习旅程中,@Autowired无疑是一个高频出现却又让初学者头疼的注解,它看似简单,却蕴含着Sprin... 目录深入浅出Spring中的@Autowired:自动注入的奥秘什么是依赖注入?@Autowired

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Java Scanner类解析与实战教程

《JavaScanner类解析与实战教程》JavaScanner类(java.util包)是文本输入解析工具,支持基本类型和字符串读取,基于Readable接口与正则分隔符实现,适用于控制台、文件输... 目录一、核心设计与工作原理1.底层依赖2.解析机制A.核心逻辑基于分隔符(delimiter)和模式匹