Android源码分析 - onSaveInstanceState、onRestoreInstanceState 状态保存与恢复
创始人
2025-05-28 03:13:49
0

本文基于 Android8.0 源码

0. 相关分享

Android源码分析 - Parcel 与 Parcelable

Android特别的数据结构(二)ArrayMap源码解析

Android源码分析 —— Activity栈管理(基于Android8)

Android-全面理解Binder原理

Android从屏幕刷新到View的绘制(一)之 Window、WindowManager和WindowManagerService之间的关系

1. 何时会调用 onSaveInstanceState?

onSaveInstanceState(Bundle savedInstance) 是 Android 用来保存一些异常情况下(例如由横竖屏切换等)而导致 Activity 销毁的数据。通过这个方式来保持 Activity 状态的方式,可以在下次再次打开此 Activity 时恢复数据。当然,如果用户主动返回,例如 finish() 掉 Activity,或者按了 Home键,这是不会走 onSaveInstanceState() 方法的。

我们从源码的角度来看一下是在哪里发起 onSaveInstance() 的,来到 ActivityThread.java,AMS(ActivityManagerService)通过ApplicationThread给APP进程发送通知,调度Activity,关于Activity销毁,可能会走 onPause(),onStop(),onDestroy()。在performPauseActivity()和performStopActivity()中,在异常退出的情况下,会回调 onSaveInstanceState()进行状态保存.

1.1 handlePauseActivity() -> performPauseActivity()

//ActivityThread.java
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,boolean saveState, String reason) {//...//如果finished为true,说明是用户主动退出的Activity,例如finish()方法,或者按了Home键。if (finished) {r.activity.mFinished = true;}if (!r.activity.mFinished && saveState) {//如果不是用户主动发起关闭的,而且需要保存状态,就调用保存方法callCallActivityOnSaveInstanceState(r);}//回调Activity的onPause()方法performPauseActivityIfNeeded(r, reason);//...return !r.activity.mFinished && saveState ? r.state : null;
}private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {if (r.paused) {//如果已经pause了,不用再回调onPause()了return;}try {r.activity.mCalled = false;//通过Instrumentation回调Activity组件的onPause()方法mInstrumentation.callActivityOnPause(r.activity);} catch (Exception e) {throw e;}r.paused = true;
}

可以看到,当 ActivityThread.java 收到对某个 Activity 的onPause()请求时,首先会判断 finished 变量,它表示了 Activity 是用户主动退出的,还是尤其其他情况导致的onPaused。如果是因为后者,也就是异常因素,就会进入到 callCallActivityOnSaveInstanceState(r) 方法保存状态,然后再进入到 Activity 的 onPause() 回调。

关注到 callCallActivityOnSaveInstanceState() 的内容:

//ActivityThread.java
private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {//将数据存到 Bundle 中r.state = new Bundle();r.state.setAllowFds(false);//这个 persistable 是在配置文件中可以设置的属性,这个是持久化存储的能力,可以实现系统关机后重启的数据恢复能力。而普通的 savedInstanceState 只是存在了系统的内存中。if (r.isPersistable()) {r.persistentState = new PersistableBundle();mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,r.persistentState);} else {mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);}
}

其中,persistable是Android 5.0 提供的新的配置,在Manifest配置文件中,可以为 Activity 设置一个属性

android:persistableMode="persistAcrossReboots|persistRootOnly|persistNever"
  • persistNever:总不起作用
  • persistRootOnly:默认值,当ActivityRecord是TaskRecord的最底层时生效。
  • persistAcrossReboots:标志了的Activity都会进行持久化状态数据保存。如果所在TaskRecord之上的ActivityRecord也设置了这个值,同时也会被持久化。

如果设置了这个值,在保存状态信息的时候除了保存在 r.state 这个 Bundle对象里,还会保存在 r.persistentState 这个 PersistableBundle对象中。简单来看一下是如何持久化存储的,显然要通过文件存储:

//PersistableBundle
public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {unparcel();XmlUtils.writeMapXml(mMap, out, this);
}public static PersistableBundle restoreFromXml(XmlPullParser in) throws IOException,
XmlPullParserException {final int outerDepth = in.getDepth();final String startTag = in.getName();final String[] tagName = new String[1];int event;while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&(event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {if (event == XmlPullParser.START_TAG) {return new PersistableBundle((ArrayMap)XmlUtils.readThisArrayMapXml(in, startTag, tagName,new MyReadMapCallback()));}}return EMPTY;
}@Override
public void writeUnknownObject(Object v, String name, XmlSerializer out)throws XmlPullParserException, IOException {if (v instanceof PersistableBundle) {out.startTag(null, TAG_PERSISTABLEMAP);out.attribute(null, "name", name);((PersistableBundle) v).saveToXml(out);out.endTag(null, TAG_PERSISTABLEMAP);} else {throw new XmlPullParserException("Unknown Object o=" + v);}
}

查看到其源码,发现是通过xml文件来进行的数据持久化存储。它相比Bundle额外实现了 XmlUtils.WriteMapCallback 接口。

1.2 handleStopActivity() -> performStopActivityInner()

三个结束Activity的生命周期中,都有保存状态的尝试,onStop也不例外。

//ActivityThread.java
private void performStopActivityInner(ActivityClientRecord r,StopInfo info, boolean keepShown, boolean saveState, String reason) {//...if (r != null) {//如果stop的时候发现activity连pause都还没有,会先进行pause,然后继续stop任务performPauseActivityIfNeeded(r, reason);//尝试保存状态信息if (!r.activity.mFinished && saveState) {if (r.state == null) {//如果不是用户主动退出的Activity,且之前没有保存过状态信息,这里会调用 onSaveInstanceState()进行保存。callCallActivityOnSaveInstanceState(r);}}//如果仍然可见,但是位于下方,则不会调用onStopif (!keepShown) {try {//回调onStop()方法r.activity.performStop(false /*preserveWindow*/);} catch (Exception e) {//...}r.stopped = true;   }}
}

这里和onPause生命周期类似,都会尝试对状态信息进行保存。不同的是,如果之前已经保存过状态信息了(performPauseActivity()中已经保存过了),这里就不会再次保存,浪费资源。

1.3 handleDestroyActivity() -> performDestroyActivity()

在Destroy()的回调过程中,并没有执行状态保存,只是健壮性判断,如果之前没有调用过pause或者stop,就会调用,而在pause和stop过程中,就已经有过状态保存了。

在 handleDestroyActivity() 中,首先调用了 performDestroyActivity(),之后就开始了Activity的关闭,与WMS通信,通知当前ActivityWindow的关闭。接下来也会通过 ActivityManager.getService().activityDestroyed(token) 通知 AMS,同时将状态数据(ActivityClientRecord的数据)回传给AMS(中的ActivityRecord)

//ActivityThread.java
private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,int configChanges, boolean getNonConfigInstance) {if (finishing) {r.activity.mFinished = true;}//如果还没pause,先pauseperformPauseActivityIfNeeded(r, "destroy");//如果还没stop,先stopr.activity.performStop(r.mPreserveWindow);//最后回调onDestorymInstrumentation.callActivityOnDestroy(r.activity);
}

也就是说,只要Activity要进行关闭,不论到stop还是Destroy,都会先尝试将pause的情况走完,也就是总会调用到 performPauseActivity(),而其中也总会尝试将state状态数据进行保存。

2. onSaveInstanceState 存了什么内容?

上文可以看到,最后通过Instrumentation发起了Activity的 onSaveInstanceState() , 它最终会保存:

  1. Window下,有id且需要保存数据的View的数据信息
  2. Fragment数据信息
  3. Dialog数据信息
  4. 其他数据信息

我们首先看到调用入口 callCallActivityOnSaveInstanceState()

//ActivityThread.java
private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {r.state = new Bundle();r.state.setAllowFds(false);if (r.isPersistable()) {r.persistentState = new PersistableBundle();mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,r.persistentState);} else {mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);}
}
//Instrumentation.java
public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) {activity.performSaveInstanceState(outState);
}

接下来就来到了Activity的 performSaveInstanceState()

//Activity.java
final void performSaveInstanceState(Bundle outState) {//保存窗口信息、以及Fragment信息onSaveInstanceState(outState);//通知所有Dialog进行状态保存saveManagedDialogs(outState);mActivityTransitionState.saveState(outState);storeHasCurrentPermissionRequest(outState);
}protected void onSaveInstanceState(Bundle outState) {//保存窗口信息(保存View)outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);//保存所有Fragmet信息Parcelable p = mFragments.saveAllState();if (p != null) {outState.putParcelable(FRAGMENTS_TAG, p);}//其他...if (mAutoFillResetNeeded) {outState.putBoolean(AUTOFILL_RESET_NEEDED, true);getAutofillManager().onSaveInstanceState(outState);}getApplication().dispatchActivitySaveInstanceState(this, outState);
}

我们主要关注保存了哪些数据,首先看到 mWindow.saveHierarchyState(),Activity的Window只有PhoneWindow实现,我们直接看到PhoneWindow:

//PhoneWindow.java//这个是window content,要么是DecorView(没设置setContentView(),默认DecorView),要么是DecorView的孩子(setContentView())
ViewGroup mContentParent;@Override
public Bundle saveHierarchyState() {Bundle outState = new Bundle();if (mContentParent == null) {return outState;}//SparseArray来临时保存信息,这是一种Key为integer类型,Value为任意类型的数据结构,是Google为Android设计的内存优化的数据结构。SparseArray states = new SparseArray();//来到了ViewGroup的保存,显然这里只会保存DecorView,或者setContentView设置的视图mContentParent.saveHierarchyState(states);//包存到outState中outState.putSparseParcelableArray(VIEWS_TAG, states);//还需要保存获得焦点的是哪个View,保存它的idfinal View focusedView = mContentParent.findFocus();if (focusedView != null && focusedView.getId() != View.NO_ID) {outState.putInt(FOCUSED_ID_TAG, focusedView.getId());}// save the panelsSparseArray panelStates = new SparseArray();savePanelState(panelStates);if (panelStates.size() > 0) {outState.putSparseParcelableArray(PANELS_TAG, panelStates);}//ToolBar的信息也要保存if (mDecorContentParent != null) {SparseArray actionBarStates = new SparseArray();mDecorContentParent.saveToolbarHierarchyState(actionBarStates);outState.putSparseParcelableArray(ACTION_BAR_TAG, actionBarStates);}return outState;
}

PhoneWindow会保存View的数据、Panel的数据、ToolBar的数据。我们关注到View数据的保存。它首先会通过 ViewGroup,这个要么是 DecorView,要么是用户通过 setContentView() 设置的一个 ViewGroup,调用其 mContentParent.saveHierarchyState(),这在 View.java 中实现:

//View.java
public void saveHierarchyState(SparseArray container) {dispatchSaveInstanceState(container);
}protected void dispatchSaveInstanceState(SparseArray container) {//只要View有id,并且没有取消状态保存的标志,就可以被保存if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {//回调View的onSaveInstanceState()Parcelable state = onSaveInstanceState();if (state != null) {//将结果放到container中container.put(mID, state);}}
}

对于View本身而言,就是通过onSaveInstanceState()保存自身的状态,但是只看View.java本身的代码并没有保存什么信息,通常View级别的子类会将保存逻辑写在重写的onSaveInstanceState()中。我们关注到它的实现类,例如TextView:

//TextView.java
@Override
public Parcelable onSaveInstanceState() {//先调用父类View的onSaveInstanceState()方法,拿到一个ParcelableParcelable superState = super.onSaveInstanceState();//这个boolean来自配置文件的 freezesText 标签设置final boolean freezesText = getFreezesText();boolean hasSelection = false;int start = -1;int end = -1;//CharSequence类型的mTextif (mText != null) {//如果有选择的起始点、终止点,说明之前有光标,记录光标和选中状态start = getSelectionStart();end = getSelectionEnd();if (start >= 0 || end >= 0) {hasSelection = true;}}//如果设置了freezesText标志,或者有选中状态,就进行文字的状态保存if (freezesText || hasSelection) {SavedState ss = new SavedState(superState);if (freezesText) {//如果是富文本的内容,按富文本的方式进行保存if (mText instanceof Spanned) {final Spannable sp = new SpannableStringBuilder(mText);if (mEditor != null) {removeMisspelledSpans(sp);sp.removeSpan(mEditor.mSuggestionRangeSpan);}ss.text = sp;} else {//如果是普通文本,直接存为String类型ss.text = mText.toString();}}//保存光标信息if (hasSelection) {ss.selStart = start;ss.selEnd = end;}if (isFocused() && start >= 0 && end >= 0) {ss.frozenWithFocus = true;}ss.error = getError();if (mEditor != null) {//如果有编辑器,同时也记录编辑器的状态信息ss.editorState = mEditor.saveInstanceState();}return ss;}return superState;
}

TextView的状态存储,首先调用了父类View的默认onSaveInstanceState()实现,然后将自己的数据填入其中,包括文本信息、光标选中状态、编辑器Editor。

View的子类ViewGroup则是重写了dispatchSaveInstanceState()方法,就是收集其下所有子View的状态,进行综合保存。

@Override
protected void dispatchSaveInstanceState(SparseArray container) {super.dispatchSaveInstanceState(container);final int count = mChildrenCount;final View[] children = mChildren;for (int i = 0; i < count; i++) {View c = children[i];if ((c.mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED) {c.dispatchSaveInstanceState(container);}}
}

3. 保存的数据何去何从?

显然保存的数据存在Bundle中的,Bundle实现了Parcelable接口,我们能猜到最终这个数据会包存到某个内存中。继续猜测,APP进程可能会被杀,而且Activity的发起实际是通过AMS,我们也能够猜到这个数据是存在AMS所在进程的内存空间中。后续代码跟踪也证实了这一点:

  • 保存的数据存在AMS所在进程(SystemServer)的内存空间中(写在ActivityRecord中)。
  • 启动Activity的时候,可以通过binder通信,将保存的数据传递回去。

我们回顾到最初发起 onSaveInstanceState 的地方:

//ActivityThread.java
private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {r.state = new Bundle();r.state.setAllowFds(false);if (r.isPersistable()) {r.persistentState = new PersistableBundle();mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,r.persistentState);} else {mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);}
}

显然,我们最终将所有状态信息写到了这个 ActivityClientRecord 对象中。最后通过AMS上报生命周期状态(同时也上报了状态信息)

//ActivityThread.java
private void handlePauseActivity(IBinder token, boolean finished,boolean userLeaving, int configChanges, boolean dontReport, int seq) {//...ActivityClientRecord r = mActivities.get(token);//...performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");//...ActivityManager.getService().activityPaused(token);
}

可以看到,最后将存储后的内容交给了AMS,所有的信息保存在了AMS的ActivityRecord之中。假设Activity所在的进程被杀了,或者旋转屏幕了,再次启动这个Activity的时候,AMS复用之前的ActivityRecord,并从其中得到之前保存的数据。换句话说,存的这些状态数据,保存在了SystemServer进程中。

留存疑问,如果Activity的启动模式是SingleTask,是否会复用之前的ActivityRecord?如果是,那么保存的状态信息是否丢失了?

4. 保存的数据通过 onRestoreInstanceState() 进行恢复

Activity的 onRestoreInstanceState()方法,在ActivityThread.java中,通过 performLaunchActivity() 方法进行回调:

//ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {//1.activity.attach主要是创建Windowactivity.attach(...);//2.activity.onCreat(),分为是否persistableif(r.isPersistable()){mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);}else{mInstrumentation.callActivityOnCreate(activity, r.state);}//onStart()方法if (!r.activity.mFinished) {activity.performStart();r.stopped = false;}//r.state!=null的话,说明之前异常退出,会回调onRestoreInstanceState()if(!r.activity.mFinished){if (r.isPersistable()) {if (r.state != null || r.persistentState != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,r.persistentState);}} else if (r.state != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);}}
}

如果这个Activity是第一次进入,之前并没有异常退出,那么r.state就是空的,调用到 onCreate() 时传入的 Bundle savedInstanceState 也就是空的。同样的,如果之前没有异常退出,r.persistentState也是空的。

如果之前异常退出了(或者屏幕旋转了),那么r.state就非空,在onCreate()中可以获取到其内容,接下来也将回调 onRestoreInstanceState()

onRestoreInstanceState() 默认实现是恢复window的信息:

//Activity.java
protected void onRestoreInstanceState(Bundle savedInstanceState) {if (mWindow != null) {Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);if (windowState != null) {//恢复windowmWindow.restoreHierarchyState(windowState);}}
}

PhoneWindow.restoreHierarchyState()也是通过DecorView或者ViewGroup来进行视图数据恢复:

//PhoneWindow.java
@Override
public void restoreHierarchyState(Bundle savedInstanceState) {if (mContentParent == null) {return;}SparseArray savedStates= savedInstanceState.getSparseParcelableArray(VIEWS_TAG);if (savedStates != null) {//View数据恢复mContentParent.restoreHierarchyState(savedStates);}//焦点View恢复int focusedViewId = savedInstanceState.getInt(FOCUSED_ID_TAG, View.NO_ID);if (focusedViewId != View.NO_ID) {View needsFocus = mContentParent.findViewById(focusedViewId);if (needsFocus != null) {needsFocus.requestFocus();}}//Panels恢复SparseArray panelStates = savedInstanceState.getSparseParcelableArray(PANELS_TAG);if (panelStates != null) {restorePanelState(panelStates);}//Toolbar数据恢复if (mDecorContentParent != null) {SparseArray actionBarStates =savedInstanceState.getSparseParcelableArray(ACTION_BAR_TAG);if (actionBarStates != null) {doPendingInvalidatePanelMenu();mDecorContentParent.restoreToolbarHierarchyState(actionBarStates);}}
}

5. 保存额外信息

通过重写 onSaveInstanceState() 方法,往bundle中存入额外数据,需要注意的是,这个bundle最后也是要通过binder通信发送到AMS的,所以数据量不能太多:

//MyActivity.java
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState){//调用父类的方法(父类默认实现了View视图的状态保存)super.onSaveInstanceState(outState,outPersistentState);outStte.putString("test",str);
}

可以在 onRestoreInstanceState()中进行恢复:

@Override
public void onRestoreInstanceState(Bundle savedInstanceState,PersistableBundle persistentState){//调用父类的方法(父类默认实现了View状态的恢复)super.onRestoreInstanceState(savedInstanceState,persistentState);str = savedInstanceState.getString("temp");
}

也可以在 onCreate() 中进行恢复(检查Bundle是否为空):

@Override
protected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);if(savedInstance != null){//之前有状态数据信息保存,可能还有自己额外保存的数据str = savedInstanceState.getString("temp");}
}

6. 实验:

MainActivity如下

public class MainActivity extends AppCompatActivity {private static final String TAG = "Fy_MainActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Log.e(TAG,"onCreate");}//所有生命周期都打印//...@Overrideprotected void onSaveInstanceState(@NonNull Bundle outState) {super.onSaveInstanceState(outState);Log.e(TAG,"onSaveInstanceState");outState.putString("test","im Tu Fengyi");}@Overrideprotected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {super.onRestoreInstanceState(savedInstanceState);String s = savedInstanceState.getString("test");Log.e(TAG,"onRestoreInstanceState gets s:"+s);}
}

旋转屏幕后,打印结果为:(Android8.0):

onCreate
onStart
onResumeonPause
onSaveInstanceState
onStop
onDestroyonCreate
onStart
onRestoreinstanceState gets s:im Tu Fengyi
onResume

旋转屏幕后,打印结果为:(Android9.0 之后改了onSaveInstance()回调的位置位置)

2023-03-14 20:04:08.859 12301-12301/? E/Fy_MainActivity: onCreate
2023-03-14 20:04:08.874 12301-12301/? E/Fy_MainActivity: onStart
2023-03-14 20:04:08.898 12301-12301/? E/Fy_MainActivity: onResume
2023-03-14 20:06:14.853 12301-12301/? E/Fy_MainActivity: onPause
2023-03-14 20:06:14.855 12301-12301/? E/Fy_MainActivity: onStop
2023-03-14 20:06:14.858 12301-12301/? E/Fy_MainActivity: onSaveInstanceState
2023-03-14 20:06:14.859 12301-12301/? E/Fy_MainActivity: onDestroy
2023-03-14 20:06:14.922 12301-12301/? E/Fy_MainActivity: onCreate
2023-03-14 20:06:14.926 12301-12301/? E/Fy_MainActivity: onStart
2023-03-14 20:06:14.927 12301-12301/? E/Fy_MainActivity: onRestoreInstanceState gets s:im Tu Fengyi
2023-03-14 20:06:14.927 12301-12301/? E/Fy_MainActivity: onResume

相关内容

热门资讯

不良率上升倒逼防线前移 银行收... 银行正在给个人信贷风控“上强度”。上海证券报记者近期自业内多方了解到,不少银行零售信贷业务从审批权限...
自媒体新手如何快速涨粉?这5个... 自媒体新手如何快速涨粉?这5个技巧让你少走弯路! 嗨,我是小融。 最近很多刚入门自媒体的朋友问我,怎...
乌兰察布市财政局关于黄金领域非... 乌兰察布市财政局关于黄金领域 非法金融活动风险提示 近期,黄金价格波动频繁,市场热度持续攀升,各类假...
一只鸡蛋架“直发”俄罗斯 无锡... (来源:无锡新传媒) 转自:无锡新传媒 一只3D打印塑料鸡蛋架,成为无锡国际邮件互换局正式开通运营后...
武汉楼市开启红五月 新房成交量... 原标题:武汉楼市开启红五月 数据爆表,新房成交量较去年同期翻番 武汉城建未来中心项目营销中心现场来...
一家精神病院竟现身A股公司前十... 5月8日,有投资者发现,盛通股份前十大股东名单中,竟出现了一家精神病院的身影。这家精神病院全称为“上...
真的老了!哈登心魔难除 骑士还... 哈登又拉胯了。 刚刚过去的两场东部半决赛,骑士都输的相当狼狈,而哈登的发挥更是灾难级的。 半决赛G1...
精神病院通报成上市公司前十大股... 近日,上市公司盛通股份发布一季报,披露了前十大股东名单。其中,一家名为“上饶市广丰区十五岭山精神病医...
天溯计量发布年报 上市首年检测... 转自:中国经营网 文 近日,计量检测机构天溯计量(301449.SZ)发布了2025年年度报告。年...
原创 全... 美伊真要停火了? 一页纸协议让全球油价闪崩! 就在今天,全球市场被一条消息炸开了锅。美国白宫觉得,他...
百信银行业绩:26Q1净利润大... 4月底,中信百信银行股份有限公司(下称“百信银行”)2025年财报及2026年一季度报接连披露—— ...
美光科技股价单周飙升38% 市... 【CNMO科技消息】受全球内存芯片短缺影响,美光科技股价本周大幅上涨。截至周五收盘,美光股价报746...
江西一精神病院炒股,炒成上市公... 近日,上市公司盛通股份(002599.SZ)发布一季报,披露了前十大股东名单,其中一家名为“上饶市广...
专访中国太保副总裁俞斌:从“+... 拥抱AI(人工智能),不再是保险行业的“选择题”,而是关乎企业生存与发展的“必答题”,更是企业决胜未...
多平台优化算法:美团取消超时扣... 图片来源:界面图库 5月8日,网信中国发布消息称,生活服务类平台算法治理已取得初步成效,美团、淘宝、...
原创 2... 2025年,国内系统重要性银行名单正式公布。这是我国金融体系的核心支柱,一共21家银行入选,它们是维...
东海县供销总社:“供销+龙头企... 近日,东海县供销合作总社鼎味泰直营店正式开业。作为东海县供销系统打造的新型社企便民服务网点,该门店的...
原创 阿... 深夜,一家零食店铺的客服后台弹出一条消息:“我上次买的芒果干,这次想换个不那么酸的口味,再帮我推荐几...
和平湾全新项目前瞻 负公摊、唯... 在沈阳,如果想在主城核心区域找一块容积率低于1.5的住宅用地,难度有多大? 过去三年,沈阳主城核心区...
精神病院与国际投行高盛同在 盛... 近日,盛通股份(002599.SZ)发布一季报,其前十大股东名单中,第九位为“上饶市广丰区十五岭山精...