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

相关内容

热门资讯

在大吉订购APP订购交易亏损被...   近期,不少投资者反映在“大吉订购App”上投资白银、铂金等商品遭遇严重亏损。该平台宣称提供现货订...
铂银壹号APP商品订购交易亏损...   许多中小投资者误以为网上的“商品现货订购”是合规合法的理财渠道,殊不知这背后隐藏着巨大的合规风险...
兴鑫淘金APP贵金属订购交易亏...   白银、贵金属或其他商品类投资,除国家批准的正规期货交易场所及持牌期货公司外,市面上大量第三方交易...
铂银掘金APP无资质的违规平台...   铂银掘金等平台的投资者,往往是被“注册送现金”“充值返现券”“首单免亏”等广告话术吸引,进而下载...
八方淘金APP订购交易不合规,...   “八方淘金APP”“铂银掘金APP”“铂银壹号APP”等软件被指以“现货订购”为名,实际采用高杠...
在指尖订购APP订购商品亏损被...   指尖订购APP这类平台,表面是“订购交易”,实则是披着电商外衣的非法期货陷阱。绝大多数投资者被蒙...
在犀贝易购APP做商品订购交易...   市面上打着“现货投资”“贵金属交易”旗号的APP并不少,但真正合规、受监管的平台并不多。犀贝易购...
易达淘金APP虚假商品订购交易...   易达淘金APP存在严重的虚假宣传与违规交易行为。该平台打着“商品订购”的旗号,实则通过不合规的交...
大浪淘金APP白银订购亏损被骗...   大浪淘金APP最隐蔽的套路,在于其完全封闭的内盘交易系统。表面上,它宣称与国际贵金属市场接轨;实...
一品好购APP上订购白银出现亏...   一品好购APP原名“一品订购”,运营方为上海宝智未来信息技术有限公司。近期不少投资者反映在该平台...
九州订购APP贵金属订购投资骗...   九州订购APP正通过抖.音、快手、今日头条等平台大量投放投资广告,用“5元起投”“充值返现”“0...
坚锅淘金APP交易软件并不正规...   当前,市面上大量所谓的“现货商城订购”交易软件,早已偏离了正常的实物商品买卖,演变为高杠杆、高手...
斗金订购APP贵金属期货交易骗...   斗金订购APP的投资者往往被铺天盖地的广告宣传所诱导——注册即送现金、充值返现券等看似诱人的福利...
警惕!云启购APP违规经营,披...   "5元起投、充值返现、稳赚不赔"——这些诱人的广告语背后,可能是一个精心设计的金融陷阱。  近期...
量子淘金APP贵金属投资不合规...   "4元起投""充值返券""月入过万"——这些极具诱惑力的广告语在短视频平台、社交软件上铺天盖地。...
鑫汇智投APP贵金属商品订购骗...   鑫汇智投APP非法期货投资骗局,受害者在投资过程中根本不懂交易,也不去研究和验证这个平台是否正规...
矅光智策APP平台违规经营非法...   矅光智策APP对外宣称是“商城订购”“现货交易”,但查询其经营范围,并未显示具备开展现货期货交易...
黄金珠宝怎么选?内侧刻字都代表... 潮新闻客户端 记者 马焱 通讯员 任倩影 9月8日下午,“云游杭州 乐购金秋”——“浙城·浙放心”活...
原创 冰... 最近全球国债市场正在上演魔幻一幕: 美债、日债、欧债遭遇猛烈抛售,收益率冲到几十年新高,美国财政部都...
日韩股市开盘表现分化 上证报中国证券网讯 9月9日,日韩股市开盘表现分化,韩国综合指数开盘上涨0.26%,报6972.87...