Android手机语言切换行为,是通过设置-语言和输入法-语言来改变手机的语言,其实这个功能很少被用户使用。
- addPreferencesFromResource(R.xml.language_settings);
- <PreferenceScreen
- android:key="phone_language"
- android:title="@string/phone_language"
- android:fragment="com.android.settings.LocalePicker"
- />
- @Override
- public View onCreateView(
- LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- final View view = super.onCreateView(inflater, container, savedInstanceState);
- final ListView list = (ListView) view.findViewById(android.R.id.list);
- Utils.forcePrepareCustomPreferencesList(container, view, list, false);
- return view;
- }
- /**
- * Constructs an Adapter object containing Locale information. Content is sorted by
- * {@link LocaleInfo#label}.
- */
- public static ArrayAdapter<LocaleInfo> constructAdapter(Context context) {
- return constructAdapter(context, R.layout.locale_picker_item, R.id.locale);
- }
- public static ArrayAdapter<LocaleInfo> constructAdapter(Context context,
- final int layoutId, final int fieldId) {
- boolean isInDeveloperMode = Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
- //获取系统支持语言的信息
- final List<LocaleInfo> localeInfos = getAllAssetLocales(context, isInDeveloperMode);
- final LayoutInflater inflater =
- (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- return new ArrayAdapter<LocaleInfo>(context, layoutId, fieldId, localeInfos) {
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View view;
- TextView text;
- if (convertView == null) {
- view = inflater.inflate(layoutId, parent, false);
- text = (TextView) view.findViewById(fieldId);
- view.setTag(text);
- } else {
- view = convertView;
- text = (TextView) view.getTag();
- }
- LocaleInfo item = getItem(position);
- text.setText(item.toString());
- text.setTextLocale(item.getLocale());
- return view;
- }
- };
- }
而此方法通过getAllAssetLocales()方法获取系统支持语言的信息:
- public static List<LocaleInfo> getAllAssetLocales(Context context, boolean isInDeveloperMode) {
- final Resources resources = context.getResources();
- //获取系统所支持的语言
- final String[] locales = Resources.getSystem().getAssets().getLocales();
- List<String> localeList = new ArrayList<String>(locales.length);
- Collections.addAll(localeList, locales);
- // Don't show the pseudolocales unless we're in developer mode.
- if (!isInDeveloperMode) {
- localeList.remove("ar-XB");
- localeList.remove("en-XA");
- }
- Collections.sort(localeList);
- final String[] specialLocaleCodes = resources.getStringArray(R.array.special_locale_codes);
- final String[] specialLocaleNames = resources.getStringArray(R.array.special_locale_names);
- final ArrayList<LocaleInfo> localeInfos = new ArrayList<LocaleInfo>(localeList.size());
- for (String locale : localeList) {
- final Locale l = Locale.forLanguageTag(locale.replace('_', '-'));
- if (l == null || "und".equals(l.getLanguage())
- || l.getLanguage().isEmpty() || l.getCountry().isEmpty()) {
- continue;
- }
- if (localeInfos.isEmpty()) {
- if (DEBUG) {
- Log.v(TAG, "adding initial "+ toTitleCase(l.getDisplayLanguage(l)));
- }
- localeInfos.add(new LocaleInfo(toTitleCase(l.getDisplayLanguage(l)), l));
- } else {
- // check previous entry:
- // same lang and a country -> upgrade to full name and
- // insert ours with full name
- // diff lang -> insert ours with lang-only name
- final LocaleInfo previous = localeInfos.get(localeInfos.size() - 1);
- if (previous.locale.getLanguage().equals(l.getLanguage()) &&
- !previous.locale.getLanguage().equals("zz")) {
- if (DEBUG) {
- Log.v(TAG, "backing up and fixing " + previous.label + " to " +
- getDisplayName(previous.locale, specialLocaleCodes, specialLocaleNames));
- }
- previous.label = toTitleCase(getDisplayName(
- previous.locale, specialLocaleCodes, specialLocaleNames));
- if (DEBUG) {
- Log.v(TAG, " and adding "+ toTitleCase(
- getDisplayName(l, specialLocaleCodes, specialLocaleNames)));
- }
- localeInfos.add(new LocaleInfo(toTitleCase(
- getDisplayName(l, specialLocaleCodes, specialLocaleNames)), l));
- } else {
- String displayName = toTitleCase(l.getDisplayLanguage(l));
- if (DEBUG) {
- Log.v(TAG, "adding "+displayName);
- }
- localeInfos.add(new LocaleInfo(displayName, l));
- }
- }
- }
- Collections.sort(localeInfos);
- return localeInfos;
- }
- /**
- * Get the locales that this asset manager contains data for.
- *
- * <p>On SDK 21 (Android 5.0: Lollipop) and above, Locale strings are valid
- * <a href="https://tools.ietf.org/html/bcp47">BCP-47</a> language tags and can be
- * parsed using {@link java.util.Locale#forLanguageTag(String)}.
- *
- * <p>On SDK 20 (Android 4.4W: Kitkat for watches) and below, locale strings
- * are of the form {@code ll_CC} where {@code ll} is a two letter language code,
- * and {@code CC} is a two letter country code.
- */
- public native final String[] getLocales();
- static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
- {
- Vector<String8> locales;
- AssetManager* am = assetManagerForJavaObject(env, clazz);
- if (am == NULL) {
- return NULL;
- }
- am->getLocales(&locales);
- const int N = locales.size();
- jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
- if (result == NULL) {
- return NULL;
- }
- for (int i=0; i<N; i++) {
- jstring str = env->NewStringUTF(locales[i].string());
- if (str == NULL) {
- return NULL;
- }
- env->SetObjectArrayElement(result, i, str);
- env->DeleteLocalRef(str);
- }
- return result;
- }
通过上面初步的分析,语言的List界面就基本出来了,在getAllAssetLocales()方法中打了个断点,查看了下locales被赋值以后的值:
- public static interface LocaleSelectionListener {
- // You can add any argument if you really need it...
- public void onLocaleSelected(Locale locale);
- }
- @Override
- public void onLocaleSelected(final Locale locale) {
- if (Utils.hasMultipleUsers(getActivity())) {
- mTargetLocale = locale;
- showDialog(DLG_SHOW_GLOBAL_WARNING);
- } else {
- getActivity().onBackPressed();
- LocalePicker.updateLocale(locale);
- }
- }
- /**
- * Requests the system to update the system locale. Note that the system looks halted
- * for a while during the Locale migration, so the caller need to take care of it.
- */
- public static void updateLocale(Locale locale) {
- try {
- IActivityManager am = ActivityManagerNative.getDefault();
- Configuration config = am.getConfiguration();
- // Will set userSetLocale to indicate this isn't some passing default - the user
- // wants this remembered
- config.setLocale(locale);
- am.updateConfiguration(config);
- // Trigger the dirty bit for the Settings Provider.
- BackupManager.dataChanged("com.android.providers.settings");
- } catch (RemoteException e) {
- // Intentionally left blank
- }
- }
- public void updateConfiguration(Configuration values) {
- enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
- "updateConfiguration()");
- synchronized(this) {
- if (values == null && mWindowManager != null) {
- // sentinel: fetch the current configuration from the window manager
- values = mWindowManager.computeNewConfiguration();
- }
- if (mWindowManager != null) {
- mProcessList.applyDisplaySize(mWindowManager);
- }
- final long origId = Binder.clearCallingIdentity();
- if (values != null) {
- Settings.System.clearConfiguration(values);
- }
- updateConfigurationLocked(values, null, false, false);
- Binder.restoreCallingIdentity(origId);
- }
- }
- /**
- * @hide Erase the fields in the Configuration that should be applied
- * by the settings.
- */
- public static void clearConfiguration(Configuration inoutConfig) {
- inoutConfig.fontScale = 0;
- }
- /**
- * Do either or both things: (1) change the current configuration, and (2)
- * make sure the given activity is running with the (now) current
- * configuration. Returns true if the activity has been left running, or
- * false if <var>starting</var> is being destroyed to match the new
- * configuration.
- * @param persistent TODO
- */
- boolean updateConfigurationLocked(Configuration values,
- ActivityRecord starting, boolean persistent, boolean initLocale) {
- int changes = 0;
- if (values != null) {
- Configuration newConfig = new Configuration(mConfiguration);
- changes = newConfig.updateFrom(values);
- if (changes != 0) {
- if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
- Slog.i(TAG, "Updating configuration to: " + values);
- }
- EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
- if (values.locale != null && !initLocale) {
- saveLocaleLocked(values.locale,
- !values.locale.equals(mConfiguration.locale),
- values.userSetLocale);
- }
- mConfigurationSeq++;
- if (mConfigurationSeq <= 0) {
- mConfigurationSeq = 1;
- }
- newConfig.seq = mConfigurationSeq;
- mConfiguration = newConfig;
- Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + newConfig);
- mUsageStatsService.reportConfigurationChange(newConfig, mCurrentUserId);
- //mUsageStatsService.noteStartConfig(newConfig);
- final Configuration configCopy = new Configuration(mConfiguration);
- // TODO: If our config changes, should we auto dismiss any currently
- // showing dialogs?
- mShowDialogs = shouldShowDialogs(newConfig);
- AttributeCache ac = AttributeCache.instance();
- if (ac != null) {
- ac.updateConfiguration(configCopy);
- }
- // Make sure all resources in our process are updated
- // right now, so that anyone who is going to retrieve
- // resource values after we return will be sure to get
- // the new ones. This is especially important during
- // boot, where the first config change needs to guarantee
- // all resources have that config before following boot
- // code is executed.
- mSystemThread.applyConfigurationToResources(configCopy);
- if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
- Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
- msg.obj = new Configuration(configCopy);
- mHandler.sendMessage(msg);
- }
- for (int i=mLruProcesses.size()-1; i>=0; i--) {
- ProcessRecord app = mLruProcesses.get(i);
- try {
- if (app.thread != null) {
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
- + app.processName + " new config " + mConfiguration);
- app.thread.scheduleConfigurationChanged(configCopy);
- }
- } catch (Exception e) {
- }
- }
- Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_REPLACE_PENDING
- | Intent.FLAG_RECEIVER_FOREGROUND);
- broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
- null, AppOpsManager.OP_NONE, false, false, MY_PID,
- Process.SYSTEM_UID, UserHandle.USER_ALL);
- if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
- intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- broadcastIntentLocked(null, null, intent,
- null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
- }
- }
- }
- boolean kept = true;
- final ActivityStack mainStack = mStackSupervisor.getFocusedStack();
- // mainStack is null during startup.
- if (mainStack != null) {
- if (changes != 0 && starting == null) {
- // If the configuration changed, and the caller is not already
- // in the process of starting an activity, then find the top
- // activity to check if its configuration needs to change.
- starting = mainStack.topRunningActivityLocked(null);
- }
- if (starting != null) {
- kept = mainStack.ensureActivityConfigurationLocked(starting, changes);
- // And we need to make sure at this point that all other activities
- // are made visible with the correct configuration.
- mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes);
- }
- }
- if (values != null && mWindowManager != null) {
- mWindowManager.setNewConfiguration(mConfiguration);
- }
- return kept;
- }
此方法主要做两件事:第一,改变当前的configuration,将新的数据放进去。第二,保证正在运行的应用程序界面更新最新的configuration。先调用updateFrom()方法,遍历configuration包含的属性是否改变,如果有改变就返回一个对应的整数,如果没有改变就返回0。就语言改变而言,根据上面的分析,configuration至少有3个属性发生了改变:fontscale(之前没有设置字体的效果就不会改变)、locale和布局的direction。
- /**
- * Save the locale. You must be inside a synchronized (this) block.
- */
- private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
- if(isDiff) {
- SystemProperties.set("user.language", l.getLanguage());
- SystemProperties.set("user.region", l.getCountry());
- }
- if(isPersist) {
- SystemProperties.set("persist.sys.language", l.getLanguage());
- SystemProperties.set("persist.sys.country", l.getCountry());
- SystemProperties.set("persist.sys.localevar", l.getVariant());
- mHandler.sendMessage(mHandler.obtainMessage(SEND_LOCALE_TO_MOUNT_DAEMON_MSG, l));
- }
- }
- if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
- Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
- msg.obj = new Configuration(configCopy);
- mHandler.sendMessage(msg);
- }
- ...
- case UPDATE_CONFIGURATION_MSG: {
- final ContentResolver resolver = mContext.getContentResolver();
- Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
- } break;
- mSystemThread = ActivityThread.currentActivityThread();
- //此方法属于ActivityThread
- public final void applyConfigurationToResources(Configuration config) {
- synchronized (mResourcesManager) {
- mResourcesManager.applyConfigurationToResourcesLocked(config, null);
- }
- }
- //此方法属于ResourcesManage
- public final boolean applyConfigurationToResourcesLocked(Configuration config,
- CompatibilityInfo compat) {
- if (mResConfiguration == null) {
- mResConfiguration = new Configuration();
- }
- if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
- + mResConfiguration.seq + ", newSeq=" + config.seq);
- return false;
- }
- int changes = mResConfiguration.updateFrom(config);
- flushDisplayMetricsLocked();
- DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(Display.DEFAULT_DISPLAY);
- if (compat != null && (mResCompatibilityInfo == null ||
- !mResCompatibilityInfo.equals(compat))) {
- mResCompatibilityInfo = compat;
- changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT
- | ActivityInfo.CONFIG_SCREEN_SIZE
- | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
- }
- // set it for java, this also affects newly created Resources
- if (config.locale != null) {
- Locale.setDefault(config.locale);
- }
- Resources.updateSystemConfiguration(config, defaultDisplayMetrics, compat);
- ApplicationPackageManager.configurationChanged();
- //Slog.i(TAG, "Configuration changed in " + currentPackageName());
- Configuration tmpConfig = null;
- for (int i=mActiveResources.size()-1; i>=0; i--) {
- ResourcesKey key = mActiveResources.keyAt(i);
- Resources r = mActiveResources.valueAt(i).get();
- if (r != null) {
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
- + r + " config to: " + config);
- int displayId = key.mDisplayId;
- boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
- DisplayMetrics dm = defaultDisplayMetrics;
- final boolean hasOverrideConfiguration = key.hasOverrideConfiguration();
- if (!isDefaultDisplay || hasOverrideConfiguration) {
- if (tmpConfig == null) {
- tmpConfig = new Configuration();
- }
- tmpConfig.setTo(config);
- if (!isDefaultDisplay) {
- dm = getDisplayMetricsLocked(displayId);
- applyNonDefaultDisplayMetricsToConfigurationLocked(dm, tmpConfig);
- }
- if (hasOverrideConfiguration) {
- tmpConfig.updateFrom(key.mOverrideConfiguration);
- }
- r.updateConfiguration(tmpConfig, dm, compat);
- } else {
- r.updateConfiguration(config, dm, compat);
- }
- //Slog.i(TAG, "Updated app resources " + v.getKey()
- // + " " + r + ": " + r.getConfiguration());
- } else {
- //Slog.i(TAG, "Removing old resources " + v.getKey());
- mActiveResources.removeAt(i);
- }
- }
- return changes != 0;
- }
- for (int i=mLruProcesses.size()-1; i>=0; i--) {
- ProcessRecord app = mLruProcesses.get(i);
- try {
- if (app.thread != null) {
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
- + app.processName + " new config " + mConfiguration);
- app.thread.scheduleConfigurationChanged(configCopy);
- }
- } catch (Exception e) {
- }
- }
- public void scheduleConfigurationChanged(Configuration config) {
- updatePendingConfiguration(config);
- sendMessage(H.CONFIGURATION_CHANGED, config);
- }
- case CONFIGURATION_CHANGED:
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
- mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
- handleConfigurationChanged((Configuration)msg.obj, null);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- break;
- final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
- int configDiff = 0;
- synchronized (mResourcesManager) {
- if (mPendingConfiguration != null) {
- if (!mPendingConfiguration.isOtherSeqNewer(config)) {
- config = mPendingConfiguration;
- mCurDefaultDisplayDpi = config.densityDpi;
- updateDefaultDensity();
- }
- mPendingConfiguration = null;
- }
- if (config == null) {
- return;
- }
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
- + config);
- mResourcesManager.applyConfigurationToResourcesLocked(config, compat);
- if (mConfiguration == null) {
- mConfiguration = new Configuration();
- }
- if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
- return;
- }
- configDiff = mConfiguration.diff(config);
- mConfiguration.updateFrom(config);
- config = applyCompatConfiguration(mCurDefaultDisplayDpi);
- }
- ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
- freeTextLayoutCachesIfNeeded(configDiff);
- if (callbacks != null) {
- final int N = callbacks.size();
- for (int i=0; i<N; i++) {
- performConfigurationChanged(callbacks.get(i), config);
- }
- }
- }
- private static void performConfigurationChanged(ComponentCallbacks2 cb, Configuration config) {
- // Only for Activity objects, check that they actually call up to their
- // superclass implementation. ComponentCallbacks2 is an interface, so
- // we check the runtime type and act accordingly.
- Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
- if (activity != null) {
- activity.mCalled = false;
- }
- boolean shouldChangeConfig = false;
- if ((activity == null) || (activity.mCurrentConfig == null)) {
- shouldChangeConfig = true;
- } else {
- // If the new config is the same as the config this Activity
- // is already running with then don't bother calling
- // onConfigurationChanged
- int diff = activity.mCurrentConfig.diff(config);
- if (diff != 0) {
- // If this activity doesn't handle any of the config changes
- // then don't bother calling onConfigurationChanged as we're
- // going to destroy it.
- if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) {
- shouldChangeConfig = true;
- }
- }
- }
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
- + ": shouldChangeConfig=" + shouldChangeConfig);
- if (shouldChangeConfig) {
- cb.onConfigurationChanged(config);
- if (activity != null) {
- if (!activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + activity.getLocalClassName() +
- " did not call through to super.onConfigurationChanged()");
- }
- activity.mConfigChangeFlags = 0;
- activity.mCurrentConfig = new Configuration(config);
- }
- }
- }
Android-语言设置流程分析的更多相关文章
-
Android 9.0 默认输入法的设置流程分析
Android 输入法设置文章 Android 9.0 默认输入法的设置流程分析 Android 9.0 添加预置第三方输入法/设置默认输入法(软键盘) 前言 在上一篇文章 Android 9.0 ...
-
Android恢复出厂设置流程分析【Android源码解析十】
最近看恢复出厂的一个问题,以前也查过这方面的流程,所以这里整理一些AP+framework层的流程: 在setting-->备份与重置--->恢复出厂设置--->重置手机---> ...
-
android Camera 数据流程分析
这篇文章主要针对其数据流程进行分析.Camera一般用于图像浏览.拍照和视频录制.这里先对图像浏览和拍照的数据流进行分析,后面再对视频电话部分进行分析. 1.针对HAL层对摄像头数据处理补充一下 Li ...
-
Android SDCard Mount 流程分析
前段时间对Android 的SDCard unmount 流程进行了几篇简短的分析,由于当时只是纸上谈兵,没有实际上的跟进,可能会有一些误导人或者小错误.今天重新梳理了头绪,针对mount的流程再重新 ...
-
android PakageManagerService启动流程分析
PakageManagerService的启动流程图 1.PakageManagerService概述 PakageManagerService是android系统中一个核心的服务,它负责系统中Pac ...
-
android添加账户流程分析涉及漏洞修复
android修复了添加账户代码中的2处bug,retme取了很酷炫的名字launchAnyWhere.broadAnywhere(参考资料1.2).本文顺着前辈的思路学习bug的原理和利用思路. 我 ...
-
Android 呼吸灯流程分析
一.Android呼吸灯Driver实现 1.注册驱动 代码位置:mediatek/kernel/drivers/leds/leds_drv.c 602static struct platform_d ...
-
Android WiFi 扫描流程分析(wpa_supplicant选择网络)
扫描流程 1.如果之前就已经有相关记录,优化扫描,扫描记录部分的频率信道. 2.如果1中的扫描没有结果,清除黑名单中的进行选择. 3.如果2中没有结果,进行所有频率的信道进行扫描 相关log参考: h ...
-
Android WiFi 扫描流程分析(wpa_supplicant)
void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) { int res; if (wpa_s-& ...
随机推荐
-
nginx反向代理编译异常
cc1: warnings being treated as errors /root/nginx_tcp_proxy_module/ngx_tcp.c: 在函数‘ngx_tcp_add_addrs’ ...
-
SQLite函数详解之二
sqlite3支持的数据类型: NULL.INTEGER.REAL.TEXT.BLOB 但是,sqlite3也支持如下的数据类型 smallint 16位整数 integer ...
-
Java 开发@ JDBC链接SQLServer2012
下面请一字一句地看,一遍就设置成功,比你设置几十遍失败,费时会少得多. 首先,在连接数据库之前必须保证SQL Server 2012是采用SQL Server身份验证方式而不是windows身份验证方 ...
-
Intent 传值和 Bundle传值的区别
http://blog.csdn.net/yanzi1225627/article/details/7802819 举个例子 我现在要从A界面 跳转到B界面或者C界面 这样的话 我就需要写2 ...
-
android-Activity的执行流程
概述 The following diagram shows the important state paths of an Activity. The square rectangles repre ...
-
文档数据库RavenDB-介绍与初体验
文档数据库RavenDB-介绍与初体验 阅读目录 1.RavenDB概述与特性 2.RavenDB安装 3.C#开发初体验 4.RavenDB资源 不知不觉,“.NET平台开源项目速览“系列文章已经1 ...
-
sklearn.neural_network.MLPClassifier参数说明
目录 sklearn.neural_network.MLPClassifier sklearn.neural_network.MLPClassifier MLPClassifier(hidden_la ...
-
数据库sql的in操作,解决in的过多
一个sql的拼写后,服务器会把这个sql传送到数据库服务器执行,一般不在一个物理机上.那么传送需要走网络,包丢失等网络情况就可能出现. 一般情况,一个sql的长度不会很大,但是有种这样的情况.in操作 ...
-
基于MySQL自增ID字段增量扫描研究
目录 目录 1 1. 问题 1 2. 背景 1 3. InnoDB表 2 3.1. 自增ID为主键 2 3.2. 自增ID为普通索引 4 3.3. 原因分析 7 4. MyISAM表 8 4.1. 自 ...
-
vue 钩子函数 使用async await
示例: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <tit ...