文档章节

从应用启动看Activity的创建过程

Kobe_Gong_5
 Kobe_Gong_5
发布于 2015/06/20 00:47
字数 1966
阅读 19
收藏 0
点赞 0
评论 0

本篇暂未完成。
/*
*Acitivity的创建过程:
*应用程序的入口为ActivityThread的main函数。
*在main函数中:
*/
public static void main(String[] args) {
SamplingProfilerIntegration.start();

// CloseGuard defaults to true and can be quite spammy. We// disable it here, but selectively enable it later (via// StrictMode) on debug builds, but using DropBox, not logs.CloseGuard.setEnabled(false);//为当前的User初始化一个用户目录,以及一些环境变量Environment.initForCurrentUser();// Set the reporter for event logging in libcoreEventLogger.setReporter(new EventLoggingReporter());


        Security.addProvider(new AndroidKeyStoreProvider());// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);


        Process.setArgV0("<pre-initialized>");


        Looper.prepareMainLooper();//创建了一个AcitivityThread,ActivityThread thread = new ActivityThread();thread.attach(false);if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }


        AsyncTask.init();if (false) {
            Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));
        }


        Looper.loop();


        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

private void attach(boolean system) {//将当前的ActivityThread对象赋值给ActivityThread的静态变量sCurrentActivityThreadsCurrentActivityThread = this;
        mSystemThread = system;//system=falseif (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {@Overridepublic void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());//ActivityManagerNative属于IPC代理类,IPC服务端是ActivityManagerServicefinal IActivityManager mgr = ActivityManagerNative.getDefault();try {/*IPC调用attachApplication,aAppThread是ApplicationThread类型。 ApplicationThread继承于ApplicationThreadNative,ApplicationThreadNative继承于Binder。 Application创建之前的一些工作 */mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {// Ignore}// Watch for getting close to heap limit.BinderInternal.addGcWatcher(new Runnable() {@Override public void run() {if (!mSomeActivitiesChanged) {return;
                    }
                    Runtime runtime = Runtime.getRuntime();long dalvikMax = runtime.maxMemory();long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();if (dalvikUsed > ((3*dalvikMax)/4)) {if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                                + " total=" + (runtime.totalMemory()/1024)
                                + " used=" + (dalvikUsed/1024));
                        mSomeActivitiesChanged = false;try {
                            mgr.releaseSomeActivities(mAppThread);
                        } catch (RemoteException e) {
                        }
                    }
                }
            });
        } else {//由于system为false,所以此处不执行android.ddm.DdmHandleAppName.setAppName("system_process",
                    UserHandle.myUserId());try {//接下来是创建ContextImpl,Application,调用Application的onCreatemInstrumentation = new Instrumentation();
                ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } catch (Exception e) {throw new RuntimeException("Unable to instantiate Application():" + e.toString(), e);
            }
        }// add dropbox logging to libcoreDropBox.setReporter(new DropBoxReporter());

        ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {@Overridepublic void onConfigurationChanged(Configuration newConfig) {synchronized (mResourcesManager) {// We need to apply this change to the resources// immediately, because upon returning the view// hierarchy will be informed about it.if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {// This actually changed the resources! Tell// everyone about it.if (mPendingConfiguration == null ||
                                mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                            mPendingConfiguration = newConfig;

                            sendMessage(H.CONFIGURATION_CHANGED, newConfig);
                        }
                    }
                }
            }@Overridepublic void onLowMemory() {
            }@Overridepublic void onTrimMemory(int level) {
            }
        });
    }//在ActivityManagerService.java中:@Overridepublic final void attachApplication(IApplicationThread thread) {synchronized (this) {int callingPid = Binder.getCallingPid();final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {// Find the application record that is being attached... either via// the pid if we are running in multiple processes, or just pull the// next app record if we are emulating process with anonymous threads.ProcessRecord app;if (pid != MY_PID && pid >= 0) {synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);
            }
        } else {
            app = null;
        }if (app == null) {
            Slog.w(TAG, "No pending application record for pid " + pid
                    + " (IApplicationThread " + thread + "); dropping process");
            EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);if (pid > 0 && pid != MY_PID) {
                Process.killProcessQuiet(pid);//TODO: Process.killProcessGroup(app.info.uid, pid);} else {try {
                    thread.scheduleExit();
                } catch (Exception e) {// Ignore exceptions.}
            }return false;
        }//此处省去部分代码   ......boolean badApp = false;boolean didSomething = false;// See if the top visible activity is waiting to run in this process...if (normalMode) {try {if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }//此处省去部分代码   ......return true;
    }     boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {final String processName = app.processName;boolean didSomething = false;for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {final ActivityStack stack = stacks.get(stackNdx);if (!isFrontStack(stack)) {continue;
                }
                ActivityRecord hr = stack.topRunningActivityLocked(null);if (hr != null) {if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                            && processName.equals(hr.processName)) {try {if (realStartActivityLocked(hr, app, true, true)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                            Slog.w(TAG, "Exception in new application when starting activity "  + hr.intent.getComponent().flattenToShortString(), e);throw e;
                        }
                    }
                }
            }
        }if (!didSomething) {
            ensureActivitiesVisibleLocked(null, 0);
        }return didSomething;
    }final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)throws RemoteException {

        r.startFreezingScreenLocked(app, 0);if (false) Slog.d(TAG, "realStartActivity: setting app visibility true");
        mWindowManager.setAppVisibility(r.appToken, true);

       ......//在此处通过IPC方式调用了ActivityThread的scheduleLaunchActivity,//scheduleLaunchActivity方法向主线程消息队列中发送了一个LAUNCH_ACTIVITY的消息。app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState,
                    results, newIntents, !andResume, mService.isNextTransitionForward(),
                    profilerInfo);//此处省去部分代码......return true;
    }//到此在ActivityThread.java.attch()中的mgr.attachApplication(mAppThread);这句代码就执行完了。//attach方法执行完后,ActivityThread的Handler就去执行LAUNCH_ACTIVITY的消息了。也就是执行handleLaunchActivity().private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {// If we are getting ready to gc after going to the background, well// we are back active so skip it.unscheduleGcIdler();
        mSomeActivitiesChanged = true;//此处省去部分代码......//此处终于创建了AcitivityActivity a = performLaunchActivity(r, customIntent);if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);//此处省去部分代码   .....

        } else {// If there was an error, for any reason, tell the activity// manager to stop us.try {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
            } catch (RemoteException ex) {// Ignore}
        }
    }//这里有两个重要的方法。//1.performLaunchActivity。//2.handleResumeActivityprivate Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");ActivityInfo aInfo = r.activityInfo;if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        ComponentName component = r.intent.getComponent();if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

        Activity activity = null;try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();//此处创建了Activity对象activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {if (!mInstrumentation.onException(activity, e)) {throw new RuntimeException("Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }try {//创建Application对象Application app = r.packageInfo.makeApplication(false, mInstrumentation);if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);

                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.voiceInteractor);if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                activity.mStartedActivity = false;//在此设置activity的主题int theme = r.activityInfo.getThemeResource();if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;//调用Activity的onCreate方法if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }if (!activity.mCalled) {throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString() +" did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;//调用activity的onStart方法if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }//调用activity的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的onPostCreate方法if (!r.activity.mFinished) {
                    activity.mCalled = false;if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }if (!activity.mCalled) {throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString() +" did not call through to super.onPostCreate()");
                    }
                }
            }
            r.paused = true;

            mActivities.put(r.token, r);

        } catch (SuperNotCalledException e) {throw e;

        } catch (Exception e) {if (!mInstrumentation.onException(activity, e)) {throw new RuntimeException("Unable to start activity " + component
                    + ": " + e.toString(), e);
            }
        }return activity;
    }//调用了mInstrumentation.newActivity去创建Activity。//之后,调用了Activity的attach方法,在其中创建了window,设置了windowManager, public Activity newActivity(ClassLoader cl, String className,
            Intent intent)throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {return (Activity)cl.loadClass(className).newInstance();
    }//newActivity方法很简单,通过反射创建Activity。//看完了performLaunchActivity。就进入另一个重要的方法handleResumeActivityfinal void handleResumeActivity(IBinder token,boolean clearHide, boolean isForward, boolean reallyResume) {// If we are getting ready to gc after going to the background, well// we are back active so skip it.unscheduleGcIdler();
        mSomeActivitiesChanged = true;// TODO Push resumeArgs into the activity for considerationActivityClientRecord r = performResumeActivity(token, clearHide);if (r != null) {final Activity a = r.activity;if (localLOGV) Slog.v(
                TAG, "Resume " + r + " started activity: " +
                a.mStartedActivity + ", hideForNow: " + r.hideForNow
                + ", finished: " + a.mFinished);final int forwardBit = isForward ?
                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;// If the window hasn't yet been added to the window manager,// and this guy didn't finish itself or start another activity,// then go ahead and add the window.boolean willBeVisible = !a.mStartedActivity;if (!willBeVisible) {try {
                    willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
                            a.getActivityToken());
                } catch (RemoteException e) {
                }
            }if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }// If the window has already been added, but during resume// we started another activity, then don't yet make the// window visible.} else if (!willBeVisible) {if (localLOGV) Slog.v(
                    TAG, "Launch " + r + " mStartedActivity set");
                r.hideForNow = true;
            }// Get rid of anything left hanging around.cleanUpPendingRemoveWindows(r);// The window is now visible if it has been added, we are not// simply finishing, and we are not starting another activity.if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {if (r.newConfig != null) {if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "+ r.activityInfo.name + " with newConfig " + r.newConfig);
                    performConfigurationChanged(r.activity, r.newConfig);
                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
                    r.newConfig = null;
                }if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="+ isForward);
                WindowManager.LayoutParams l = r.window.getAttributes();if ((l.softInputMode
                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
                        != forwardBit) {
                    l.softInputMode = (l.softInputMode
                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
                            | forwardBit;if (r.activity.mVisibleFromClient) {
                        ViewManager wm = a.getWindowManager();
                        View decor = r.window.getDecorView();
                        wm.updateViewLayout(decor, l);
                    }
                }
                r.activity.mVisibleFromServer = true;
                mNumVisibleActivities++;if (r.activity.mVisibleFromClient) {
                    r.activity.makeVisible();
                }
            }if (!r.onlyLocalRequest) {
                r.nextIdle = mNewActivities;
                mNewActivities = r;if (localLOGV) Slog.v(
                    TAG, "Scheduling idle handler for " + r);
                Looper.myQueue().addIdleHandler(new Idler());
            }
            r.onlyLocalRequest = false;// Tell the activity manager we have resumed.if (reallyResume) {try {
                    ActivityManagerNative.getDefault().activityResumed(token);
                } catch (RemoteException ex) {
                }
            }

        } else {// If an exception was thrown when trying to resume, then// just end this activity.try {
                ActivityManagerNative.getDefault()
                    .finishActivity(token, Activity.RESULT_CANCELED, null, false);
            } catch (RemoteException ex) {
            }
        }
    }//先看看performResumeActivity方法。在此方法中调用activity的生命周期函数onResume。public final ActivityClientRecord performResumeActivity(IBinder token,boolean clearHide) {
        ActivityClientRecord r = mActivities.get(token);if (localLOGV) Slog.v(TAG, "Performing resume of " + r
                + " finished=" + r.activity.mFinished);if (r != null && !r.activity.mFinished) {if (clearHide) {
                r.hideForNow = false;
                r.activity.mStartedActivity = false;
            }try {
                r.activity.mFragments.noteStateNotSaved();if (r.pendingIntents != null) {
                    deliverNewIntents(r, r.pendingIntents);
                    r.pendingIntents = null;
                }if (r.pendingResults != null) {
                    deliverResults(r, r.pendingResults);
                    r.pendingResults = null;
                }//调用onResume方法r.activity.performResume();

                EventLog.writeEvent(LOG_ON_RESUME_CALLED,
                        UserHandle.myUserId(), r.activity.getComponentName().getClassName());

                r.paused = false;
                r.stopped = false;
                r.state = null;
                r.persistentState = null;
            } catch (Exception e) {if (!mInstrumentation.onException(r.activity, e)) {throw new RuntimeException("Unable to resume activity "+ r.intent.getComponent().toShortString()
                        + ": " + e.toString(), e);
                }
            }
        }return r;
    }//然后重点就是下面这段代码: if (r.window == null && !a.mFinished && willBeVisible) {//先拿到window和windowManager对象,这两个对象在上面介绍的Activity的attch方法中创建。r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;//windowManager显示decorView,此方法wm.addView(decor, l);
                }// If the window has already been added, but during resume// we started another activity, then don't yet make the// window visible.} else if (!willBeVisible) {if (localLOGV) Slog.v(
                    TAG, "Launch " + r + " mStartedActivity set");
                r.hideForNow = true;
            }

做个备注:
在ActivityThread.java中:
H是Handler的字类。负责处理Activity的各种操作。
performLaunchActivity中创建了Activity

LoadApk中存储了ActivityThread的引用,还有其他的一些关于该应用的目录等变量。
CompatibilityInfo类保存了应用程序运行的兼容性模式的信息

我们平时在Activity中使用的ContentResolver是ApplicationContentResolver类型的

© 著作权归作者所有

共有 人打赏支持
Kobe_Gong_5
粉丝 2
博文 55
码字总数 43587
作品 0
成都
Android深入四大组件(七)Android8.0 根Activity启动过程(后篇)

相关文章 Android深入四大组件系列 Android系统启动系列 Android应用程序进程系列 Android深入解析AMS系列 前言 在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)和Andro...

刘望舒
2017/12/25
0
0
Android深入四大组件(六)Android8.0 根Activity启动过程(前篇)

相关文章 Android深入四大组件系列 Android系统启动系列 Android应用程序进程系列 Android深入解析AMS系列 前言 在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)和Andro...

刘望舒
2017/11/27
0
0
Android framework——Activity的启动和创建

本人制作的app:1号密码 欢迎试用   最近学习Android相关知识,感觉仅仅了解Activity几个生命周期函数基本上没有任何意义的; 于是想深入了解一下Activity到底是怎么一回事怎么运行来的;里...

jackxu2015
2015/08/14
0
0
Android应用程序的Activity启动过程简要介绍和学习计划

在Android系统中,Activity和Service是应用程序的核心组件,它们以松藕合的方式组合在一起构成了一个完整的应用程序,这得益于应用程序框架层提供了一套完整的机制来协助应用程序启动这些Act...

坚持自己
2013/03/28
0
0
Android应用程序窗口(Activity)的窗口对象(Window)的创建过程分析

每一个Activity组件都有一个关联的ContextImpl对象,同时,它还关联有一个Window对象,用来描述一个具体的应用程序窗口。与Activity组件所关联的窗口对象的实际类型为PhoneWindow。 那么创建...

lonamessi
05/31
0
0
Android插件化原理(一)Activity插件化

相关文章 Android深入四大组件系列 Android解析AMS系列 Android解析ClassLoader系列 前言 四大组件的插件化是插件化技术的核心知识点,而Activity插件化更是重中之重,Activity插件化主要有三...

刘望舒
05/29
0
0
Android应用程序在新的进程中启动新的Activity的方法和过程分析

前面我们在分析Activity启动过程的时候,看到同一个应用程序的Activity一般都是在同一个进程中启动,事实上,Activity也可以像Service一样在新的进程中启动,这样,一个应用程序就可以跨越好...

LiSteven
2014/03/05
0
0
Activity跳转Flag详解

Android 的一个特色就是 application A 的 activity 可以启动 application B 的 activity,尽管 A 和 B 是毫无干系的,而在用户看来,两个场景紧密联系,视觉上二者构成了一个整体。Android...

今日竹石
2014/04/29
0
0
创建一个android项目与创建一个android虚拟设备

创建一个android项目 Navigator面板区点击右键-->New-->Android Application Project,打开New Android Applicaton窗口。输入Application Name(应用程序的名称,就是显示在手机上的名称,比...

柳哥
2014/09/17
0
0
Android启动过程深入解析

1.当按下Android设备电源键时究竟发生了什么? 2.Android的启动过程是怎么样的? 3.什么是Linux内核? 4.桌面系统linux内核与Android系统linux内核有什么区别? 5.什么是引导装载程序? 6.什...

AlexMahoneFBI
2015/11/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

java集合元素的默认大小

当底层实现涉及到扩容时,容器或重新分配一段更大的连续内存(如果是离散分配则不需要重新分配,离散分配都是插入新元素时动态分配内存),要将容器原来的数据全部复制到新的内存上,这无疑使...

竹叶青出于蓝
4分钟前
1
0
Java快速开发平台,JEECG 3.7.7闪电版本发布,增加多套主流UI代码生成器模板

JEECG 3.7.7 闪电版本发布,提供5套主流UI代码生成器模板 导读 ⊙平台性能优化,速度闪电般提升 ⊙提供5套新的主流UI代码生成器模板(Bootstrap表单+BootstrapTable列表\ ElementUI列表表单)...

Jeecg
8分钟前
0
0
export 和 module.export 的区别

在浏览器端 js 里面,为了解决各模块变量冲突等问题,往往借助于 js 的闭包把左右模块相关的代码都包装在一个匿名函数里。而 Nodejs 编写模块相当的自由,开发者只需要关注 require,exports,...

孟飞阳
10分钟前
0
0
技术教育的兴起

技术教育的兴起 作者: 阮一峰 1、 有一年,我在台湾环岛旅行。 花莲的海边,我遇到一对台湾青年夫妻,带着女儿在海滩上玩。我们聊了起来。 当时,我还在高校当老师。他们问我,是否觉得台湾...

吕伯文
10分钟前
0
0
Linux服务器下的HTTP抓包分析

说到抓包分析,最简单的办法莫过于在客户端直接安装一个Wireshark或者Fiddler了,但是有时候由于客户端开发人员(可能是第三方)知识欠缺或者其它一些原因,无法顺利的在客户端进行抓包分析,...

mylxsw
15分钟前
0
0
mybatis3-javaapi

sqlSessionFactoryBuilder->sqlSessionFactory->sqlSession<-rowbound<-resultHandler myBatis uses a Java enumeration wrapper for transaction isolation levels, called TransactionIsol......

writeademo
18分钟前
0
0
Java NIO:浅析I/O模型

也许很多朋友在学习NIO的时候都会感觉有点吃力,对里面的很多概念都感觉不是那么明朗。在进入Java NIO编程之前,我们今天先来讨论一些比较基础的知识:I/O模型。下面本文先从同步和异步的概念...

yzbty23
18分钟前
0
0
了解iOS消息推送一文就够:史上最全iOS Push技术详解

本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表。 1、引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ、微信等IM界面处于前台时,聊天消息和指令都会...

JackJiang-
20分钟前
0
0
Mysql汉子转拼音

update t_app_city SET CITY_NAME_BEGIN = ELT(INTERVAL(CONV(HEX(LEFT(CONVERT(CITY_NAME USING gbk),1)),16,10), 0xB0A1,0xB0C5,0xB2C1,0xB4EE,0xB6EA,0xB7A2,0xB8C1,0xB9FE,0xBBF7, 0xBFA......

尘叙缘
22分钟前
0
0
大数据构建智慧城市“新引擎”,加速推进新旧动能转换

——“大数据与智慧城市”技术交流分享会——济南站召开 7月13日,“大数据携手智慧城市,助力山东新旧动能转换”技术交流分享会——济南站在山东信息通信技术研究院会议室成功举办,此次会议...

左手的倒影
24分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部