分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应用程序就是Launcher了,本文将详细分析Launcher应用程序的启动过程。

《Android系统源代码情景分析》一书正在进击的程序员网(http://0xcc0xcd.com)中连载,点击进入!

Android系统的Home应用程序Launcher是由ActivityManagerService启动的,而ActivityManagerService和PackageManagerService一样,都是在开机时由SystemServer组件启动的,SystemServer组件首先是启动ePackageManagerServic,由它来负责安装系统的应用程序,具体可以参考前面一篇文章Android应用程序安装过程源代码分析,系统中的应用程序安装好了以后,SystemServer组件接下来就要通过ActivityManagerService来启动Home应用程序Launcher了,Launcher在启动的时候便会通过PackageManagerServic把系统中已经安装好的应用程序以快捷图标的形式展示在桌面上,这样用户就可以使用这些应用程序了,整个过程如下图所示:

点击查看大图

下面详细分析每一个步骤。

Step 1. SystemServer.main

这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 1。

Step 2. SystemServer.init1

这个函数是一个JNI方法,实现在 frameworks/base/services/jni/com_android_server_SystemServer.cpp文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 2。

Step 3. libsystem_server.system_init

函数system_init实现在libsystem_server库中,源代码位于frameworks/base/cmds/system_server/library/system_init.cpp文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 3。

Step 4. AndroidRuntime.callStatic

这个函数定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 4。

Step 5. SystemServer.init2

这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 5。

Step 6. ServerThread.run

这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 6。

Step 7. ActivityManagerService.main

这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerServcie.java文件中:

public final class ActivityManagerService extends ActivityManagerNative  implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { ...... public static final Context main(int factoryTest) {  AThread thr = new AThread();  thr.start();  synchronized (thr) {   while (thr.mService == null) {    try {     thr.wait();    } catch (InterruptedException e) {    }   }  }  ActivityManagerService m = thr.mService;  mSelf = m;  ActivityThread at = ActivityThread.systemMain();  mSystemThread = at;  Context context = at.getSystemContext();  m.mContext = context;  m.mFactoryTest = factoryTest;  m.mMainStack = new ActivityStack(m, context, true);  m.mBatteryStatsService.publish(context);  m.mUsageStatsService.publish(context);  synchronized (thr) {   thr.mReady = true;   thr.notifyAll();  }  m.startRunning(null, null, null, null);  return context; } ......}

这个函数首先通过AThread线程对象来内部创建了一个ActivityManagerService实例,然后将这个实例保存其成员变量mService中,接着又把这个ActivityManagerService实例保存在ActivityManagerService类的静态成员变量mSelf中,最后初始化其它成员变量,就结束了。

Step 8. PackageManagerService.main

这个函数定义在frameworks/base/services/java/com/android/server/PackageManagerService.java文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 7。执行完这一步之后,系统中的应用程序的所有信息都保存在PackageManagerService中了,后面Home应用程序Launcher启动起来后,就会把PackageManagerService中的应用程序信息取出来,然后以快捷图标的形式展示在桌面上,后面我们将会看到这个过程。

Step 9. ActivityManagerService.setSystemProcess

这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerServcie.java文件中:

public final class ActivityManagerService extends ActivityManagerNative  implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { ...... public static void setSystemProcess() {  try {   ActivityManagerService m = mSelf;   ServiceManager.addService("activity", m);   ServiceManager.addService("meminfo", new MemBinder(m));   if (MONITOR_CPU_USAGE) {    ServiceManager.addService("cpuinfo", new CpuBinder(m));   }   ServiceManager.addService("permission", new PermissionController(m));   ApplicationInfo info =    mSelf.mContext.getPackageManager().getApplicationInfo(    "android", STOCK_PM_FLAGS);   mSystemThread.installSystemApplicationInfo(info);   synchronized (mSelf) {    ProcessRecord app = mSelf.newProcessRecordLocked(     mSystemThread.getApplicationThread(), info,     info.processName);    app.persistent = true;    app.pid = MY_PID;    app.maxAdj = SYSTEM_ADJ;    mSelf.mProcessNames.put(app.processName, app.info.uid, app);    synchronized (mSelf.mPidsSelfLocked) {     mSelf.mPidsSelfLocked.put(app.pid, app);    }    mSelf.updateLruProcessLocked(app, true, true);   }  } catch (PackageManager.NameNotFoundException e) {   throw new RuntimeException(    "Unable to find android system package", e);  } } ......}

这个函数首先是将这个ActivityManagerService实例添加到ServiceManager中去托管,这样其它地方就可以通过ServiceManager.getService接口来访问这个全局唯一的ActivityManagerService实例了,接着又通过调用mSystemThread.installSystemApplicationInfo函数来把应用程序框架层下面的android包加载进来 ,这里的mSystemThread是一个ActivityThread类型的实例变量,它是在上面的Step 7中创建的,后面就是一些其它的初始化工作了。

Step 10.  ActivityManagerService.systemReady

这个函数是在上面的Step 6中的ServerThread.run函数在将系统中的一系列服务都初始化完毕之后才调用的,它定义在frameworks/base/services/java/com/android/server/am/ActivityManagerServcie.java文件中:

public final class ActivityManagerService extends ActivityManagerNative  implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { ...... public void systemReady(final Runnable goingCallback) {  ......  synchronized (this) {   ......   mMainStack.resumeTopActivityLocked(null);  } } ......}

这个函数的内容比较多,这里省去无关的部分,主要关心启动Home应用程序的逻辑,这里就是通过mMainStack.resumeTopActivityLocked函数来启动Home应用程序的了,这里的mMainStack是一个ActivityStack类型的实例变量。

Step 11. ActivityStack.resumeTopActivityLocked

这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中:

public class ActivityStack { ...... final boolean resumeTopActivityLocked(ActivityRecord prev) {  // Find the first activity that is not finishing.  ActivityRecord next = topRunningActivityLocked(null);  ......  if (next == null) {   // There are no more activities!  Let's just start up the   // Launcher...   if (mMainStack) {    return mService.startHomeActivityLocked();   }  }  ...... } ......}

这里调用函数topRunningActivityLocked返回的是当前系统Activity堆栈最顶端的Activity,由于此时还没有Activity被启动过,因此,返回值为null,即next变量的值为null,于是就调用mService.startHomeActivityLocked语句,这里的mService就是前面在Step 7中创建的ActivityManagerService实例了。

Step 12. ActivityManagerService.startHomeActivityLocked

这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerServcie.java文件中:

public final class ActivityManagerService extends ActivityManagerNative  implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { ...... boolean startHomeActivityLocked() {  ......  Intent intent = new Intent(   mTopAction,   mTopData != null ? Uri.parse(mTopData) : null);  intent.setComponent(mTopComponent);  if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {   intent.addCategory(Intent.CATEGORY_HOME);  }  ActivityInfo aInfo =   intent.resolveActivityInfo(mContext.getPackageManager(),   STOCK_PM_FLAGS);  if (aInfo != null) {   intent.setComponent(new ComponentName(    aInfo.applicationInfo.packageName, aInfo.name));   // Don't do this if the home app is currently being   // instrumented.   ProcessRecord app = getProcessRecordLocked(aInfo.processName,    aInfo.applicationInfo.uid);   if (app == null || app.instrumentationClass == null) {    intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);    mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,     null, null, 0, 0, 0, false, false);   }  }  return true; } ......}

函数首先创建一个CATEGORY_HOME类型的Intent,然后通过Intent.resolveActivityInfo函数向PackageManagerService查询Category类型为HOME的Activity,这里我们假设只有系统自带的Launcher应用程序注册了HOME类型的Activity(见packages/apps/Launcher2/AndroidManifest.xml文件):

<manifest    xmlns:android="http://schemas.android.com/apk/res/android"    package="com.android.launcher"    android:sharedUserId="@string/sharedUserId" >    ...... <application     android:name="com.android.launcher2.LauncherApplication"     android:process="@string/process"     android:label="@string/application_name"     android:icon="@drawable/ic_launcher_home">  <activity   android:name="com.android.launcher2.Launcher"   android:launchMode="singleTask"   android:clearTaskOnLaunch="true"   android:stateNotNeeded="true"   android:theme="@style/Theme"   android:screenOrientation="nosensor"   android:windowSoftInputMode="stateUnspecified|adjustPan">   <intent-filter>    <action android:name="android.intent.action.MAIN" />    <category android:name="android.intent.category.HOME" />    <category android:name="android.intent.category.DEFAULT" />    <category android:name="android.intent.category.MONKEY"/>    </intent-filter>  </activity>  ...... </application></manifest>

因此,这里就返回com.android.launcher2.Launcher这个Activity了。由于是第一次启动这个Activity,接下来调用函数getProcessRecordLocked返回来的ProcessRecord值为null,于是,就调用mMainStack.startActivityLocked函数启动com.android.launcher2.Launcher这个Activity了,这里的mMainStack是一个ActivityStack类型的成员变量。

Step 13.  ActivityStack.startActivityLocked

这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中,具体可以参考Android应用程序启动过程源代码分析一文,这里就不详述了,在我们这个场景中,调用这个函数的最后结果就是把com.android.launcher2.Launcher启动起来,接着调用它的onCreate函数。

Step 14. Launcher.onCreate

这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/Launcher.java文件中:

public final class Launcher extends Activity  implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher { ...... @Override protected void onCreate(Bundle savedInstanceState) {  ......  if (!mRestoring) {   mModel.startLoader(this, true);  }  ...... } ......}

这里的mModel是一个LauncherModel类型的成员变量,这里通过调用它的startLoader成员函数来执行加应用程序的操作。

Step 15. LauncherModel.startLoader

这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/LauncherModel.java文件中:

public class LauncherModel extends BroadcastReceiver { ...... public void startLoader(Context context, boolean isLaunching) {  ......                synchronized (mLock) {                     ......                     // Don't bother to start the thread if we know it's not going to do anything                     if (mCallbacks != null && mCallbacks.get() != null) {                         // If there is already one running, tell it to stop.                         LoaderTask oldTask = mLoaderTask;                         if (oldTask != null) {                             if (oldTask.isLaunching()) {                                 // don't downgrade isLaunching if we're already running                                 isLaunching = true;                             }                             oldTask.stopLocked();           }           mLoaderTask = new LoaderTask(context, isLaunching);           sWorker.post(mLoaderTask);             }        } } ......}

这里不是直接加载应用程序,而是把加载应用程序的操作作为一个消息来处理。这里的sWorker是一个Handler,通过它的post方式把一个消息放在消息队列中去,然后系统就会调用传进去的参数mLoaderTask的run函数来处理这个消息,这个mLoaderTask是LoaderTask类型的实例,于是,下面就会执行LoaderTask类的run函数了。

Step 16. LoaderTask.run

这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/LauncherModel.java文件中:

public class LauncherModel extends BroadcastReceiver { ...... private class LoaderTask implements Runnable {  ......  public void run() {   ......   keep_running: {    ......    // second step    if (loadWorkspaceFirst) {     ......     loadAndBindAllApps();    } else {     ......    }    ......   }   ......  }  ...... } ......}

这里调用loadAndBindAllApps成员函数来进一步操作。

Step 17. LoaderTask.loadAndBindAllApps
        这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/LauncherModel.java文件中:

public class LauncherModel extends BroadcastReceiver { ...... private class LoaderTask implements Runnable {  ......  private void loadAndBindAllApps() {   ......   if (!mAllAppsLoaded) {    loadAllAppsByBatch();    if (mStopped) {     return;    }    mAllAppsLoaded = true;   } else {    onlyBindAllApps();   }  }  ...... } ......}

由于还没有加载过应用程序,这里的mAllAppsLoaded为false,于是就继续调用loadAllAppsByBatch函数来进一步操作了。

Step 18. LoaderTask.loadAllAppsByBatch
        这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/LauncherModel.java文件中:

public class LauncherModel extends BroadcastReceiver { ...... private class LoaderTask implements Runnable {  ......  private void loadAllAppsByBatch() {    ......   final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);   mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);   final PackageManager packageManager = mContext.getPackageManager();   List<ResolveInfo> apps = null;   int N = Integer.MAX_VALUE;   int startIndex;   int i=0;   int batchSize = -1;   while (i < N && !mStopped) {    if (i == 0) {     mAllAppsList.clear();     ......     apps = packageManager.queryIntentActivities(mainIntent, 0);          ......     N = apps.size();          ......     if (mBatchSize == 0) {      batchSize = N;     } else {      batchSize = mBatchSize;     }     ......     Collections.sort(apps,      new ResolveInfo.DisplayNameComparator(packageManager));    }    startIndex = i;    for (int j=0; i<N && j<batchSize; j++) {     // This builds the icon bitmaps.     mAllAppsList.add(new ApplicationInfo(apps.get(i), mIconCache));     i++;    }    final boolean first = i <= batchSize;    final Callbacks callbacks = tryGetCallbacks(oldCallbacks);    final ArrayList<ApplicationInfo> added = mAllAppsList.added;    mAllAppsList.added = new ArrayList<ApplicationInfo>();       mHandler.post(new Runnable() {     public void run() {      final long t = SystemClock.uptimeMillis();      if (callbacks != null) {       if (first) {        callbacks.bindAllApplications(added);       } else {        callbacks.bindAppsAdded(added);       }       ......      } else {       ......      }     }    });    ......   }   ......  }  ...... } ......}

函数首先构造一个CATEGORY_LAUNCHER类型的Intent:

    final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);    mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);

接着从mContext变量中获得PackageManagerService的接口:

    final PackageManager packageManager = mContext.getPackageManager();

下一步就是通过这个PackageManagerService.queryIntentActivities接口来取回所有Action类型为Intent.ACTION_MAIN,并且Category类型为Intent.CATEGORY_LAUNCHER的Activity了。

我们先进入到PackageManagerService.queryIntentActivities函数中看看是如何获得这些Activity的,然后再回到这个函数中来看其余操作。

Step 19. PackageManagerService.queryIntentActivities

这个函数定义在frameworks/base/services/java/com/android/server/PackageManagerService.java文件中:

class PackageManagerService extends IPackageManager.Stub { ...... public List<ResolveInfo> queryIntentActivities(Intent intent,   String resolvedType, int flags) {  ......  synchronized (mPackages) {   String pkgName = intent.getPackage();   if (pkgName == null) {    return (List<ResolveInfo>)mActivities.queryIntent(intent,      resolvedType, flags);   }   ......  }  ...... } ......}

回忆前面一篇文章Android应用程序安装过程源代码分析,系统在前面的Step 8中启动PackageManagerService时,会把系统中的应用程序都解析一遍,然后把解析得到的Activity都保存在mActivities变量中,这里通过这个mActivities变量的queryIntent函数返回符合条件intent的Activity,这里要返回的便是Action类型为Intent.ACTION_MAIN,并且Category类型为Intent.CATEGORY_LAUNCHER的Activity了。

回到Step 18中的 LoaderTask.loadAllAppsByBatch函数中,从queryIntentActivities函数调用处返回所要求的Activity后,便调用函数tryGetCallbacks(oldCallbacks)得到一个返CallBack接口,这个接口是由Launcher类实现的,接着调用这个接口的.bindAllApplications函数来进一步操作。注意,这里又是通过消息来处理加载应用程序的操作的。

Step 20. Launcher.bindAllApplications

这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/Launcher.java文件中:

public final class Launcher extends Activity  implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher { ...... private AllAppsView mAllAppsGrid; ...... public void bindAllApplications(ArrayList<ApplicationInfo> apps) {  mAllAppsGrid.setApps(apps); } ......}

这里的mAllAppsGrid是一个AllAppsView类型的变量,它的实际类型一般就是AllApps2D了。

Step 21. AllApps2D.setApps

这个函数定义在packages/apps/Launcher2/src/com/android/launcher2/AllApps2D.java文件中:

public class AllApps2D extends RelativeLayout implements AllAppsView,  AdapterView.OnItemClickListener,  AdapterView.OnItemLongClickListener,  View.OnKeyListener,  DragSource { ...... public void setApps(ArrayList<ApplicationInfo> list) {  mAllAppsList.clear();  addApps(list); } public void addApps(ArrayList<ApplicationInfo> list) {  final int N = list.size();  for (int i=0; i<N; i++) {   final ApplicationInfo item = list.get(i);   int index = Collections.binarySearch(mAllAppsList, item,    LauncherModel.APP_NAME_COMPARATOR);   if (index < 0) {    index = -(index+1);   }   mAllAppsList.add(index, item);  }  mAppsAdapter.notifyDataSetChanged(); } ......}

函数setApps首先清空mAllAppsList列表,然后调用addApps函数来为上一步得到的每一个应用程序创建一个ApplicationInfo实例了,有了这些ApplicationInfo实例之后,就可以在桌面上展示系统中所有的应用程序了。

到了这里,系统默认的Home应用程序Launcher就把PackageManagerService中的应用程序加载进来了,当我们在屏幕上点击下面这个图标时,就会把刚才加载好的应用程序以图标的形式展示出来了:

点击这个按钮时,便会响应Launcher.onClick函数:

public final class Launcher extends Activity  implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher { ...... public void onClick(View v) {  Object tag = v.getTag();  if (tag instanceof ShortcutInfo) {   ......  } else if (tag instanceof FolderInfo) {   ......  } else if (v == mHandleView) {   if (isAllAppsVisible()) {    ......   } else {    showAllApps(true);   }  } } ......}

接着就会调用showAllApps函数显示应用程序图标:

public final class Launcher extends Activity  implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher { ...... void showAllApps(boolean animated) {  mAllAppsGrid.zoom(1.0f, animated);  ((View) mAllAppsGrid).setFocusable(true);  ((View) mAllAppsGrid).requestFocus();  // TODO: fade these two too  mDeleteZone.setVisibility(View.GONE); } ......}

这样我们就可以看到系统中的应用程序了:

当点击上面的这些应用程序图标时,便会响应AllApps2D.onItemClick函数:

public class AllApps2D extends RelativeLayout implements AllAppsView,  AdapterView.OnItemClickListener,  AdapterView.OnItemLongClickListener,  View.OnKeyListener,  DragSource { ...... public void onItemClick(AdapterView parent, View v, int position, long id) {  ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);  mLauncher.startActivitySafely(app.intent, app); } ......}

这里的成员变量mLauncher的类型为Launcher,于是就调用Launcher.startActivitySafely函数来启动应用程序了,这个过程具体可以参考Android应用程序启动过程源代码分析一文。

老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

你好! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

新的改变

我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:

  1. 全新的界面设计 ,将会带来全新的写作体验;
  2. 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
  3. 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
  4. 全新的 KaTeX数学公式 语法;
  5. 增加了支持甘特图的mermaid语法1 功能;
  6. 增加了 多屏幕编辑 Markdown文章功能;
  7. 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
  8. 增加了 检查列表 功能。

功能快捷键

撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G

合理的创建标题,有助于目录的生成

直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

如何改变文本的样式

强调文本 强调文本

加粗文本 加粗文本

标记文本

删除文本

引用文本

H2O is是液体。

210 运算结果是 1024.

插入链接与图片

链接: link.

图片:

带尺寸的图片:

当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

如何插入一段漂亮的代码片

去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block var foo = 'bar'; 

生成一个适合你的列表

  • 项目

    • 项目

      • 项目
  1. 项目1
  2. 项目2
  3. 项目3
  • 计划任务
  • 完成任务

创建一个表格

一个简单的表格是这么创建的:

项目 Value
电脑 $1600
手机 $12
导管 $1

设定内容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列 第二列 第三列
第一列文本居中 第二列文本居右 第三列文本居左

SmartyPants

SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

TYPE ASCII HTML
Single backticks 'Isn't this fun?' ‘Isn’t this fun?’
Quotes "Isn't this fun?" “Isn’t this fun?”
Dashes -- is en-dash, --- is em-dash – is en-dash, — is em-dash

创建一个自定义列表

Markdown
Text-to-HTML conversion tool
Authors
John
Luke

如何创建一个注脚

一个具有注脚的文本。2

注释也是必不可少的

Markdown将文本转换为 HTML

KaTeX数学公式

您可以使用渲染LaTeX数学表达式 KaTeX:

Gamma公式展示 Γ(n)=(n−1)!∀n∈N\Gamma(n) = (n-1)!\quad\forall n\in\mathbb NΓ(n)=(n−1)!∀n∈N 是通过欧拉积分

Γ(z)=∫0∞tz−1e−tdt&ThinSpace;.\Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=∫0∞​tz−1e−tdt.

你可以找到更多关于的信息 LaTeX 数学表达式here.

新的甘特图功能,丰富你的文章

ganttdateFormat  YYYY-MM-DDtitle Adding GANTT diagram functionality to mermaidsection 现有任务已完成               :done,    des1, 2014-01-06,2014-01-08进行中               :active,  des2, 2014-01-09, 3d计划一               :         des3, after des2, 5d计划二               :         des4, after des3, 5d
  • 关于 甘特图 语法,参考 这儿,

UML 图表

可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图::

张三李四王五你好!李四, 最近怎么样?你最近怎么样,王五?我很好,谢谢!我很好,谢谢!李四想了很长时间,文字太长了不适合放在一行.打量着王五...很好... 王五, 你怎么样?张三李四王五

这将产生一个流程图。:

链接
长方形
圆角长方形
菱形
  • 关于 Mermaid 语法,参考 这儿,

FLowchart流程图

我们依旧会支持flowchart的流程图:

  • 关于 Flowchart流程图 语法,参考 这儿.

导出与导入

导出

如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

导入

如果你想加载一篇你写过的.md文件或者.html文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。


  1. mermaid语法说明 ↩︎

  2. 注脚的解释 ↩︎

Android系统默认Home应用程序 Launcher 的启动过程源代码分析相关推荐

  1. Android系统默认Home应用程序(Launcher)的启动过程源代码分析

    在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应 ...

  2. Android系统默认Home应用程序(Launcher)的启动过程源码分析

    在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还须要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应 ...

  3. Android系统默认Home应用程序(Launcher)的启动过程源代码分析(3)

    Step 13.  ActivityStack.startActivityLocked 这个函数定义在frameworks/base/services/java/com/android/server/ ...

  4. Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析

    原文地址: http://blog.csdn.net/luoshengyang/article/details/6629298 在前面一篇文章浅谈Android系统进程间通信(IPC)机制Binder ...

  5. Android应用程序组件Content Provider的启动过程源代码分析(1)

             通过前面的学习,我们知道在Android系统中,Content Provider可以为不同的应用程序访问相同的数据提供统一的入口.Content Provider一般是运行在独立的进 ...

  6. Android应用程序启动过程源代码分析(5)

    Step 35. MainActivity.onCreate 这个函数定义在packages/experimental/Activity/src/shy/luo/activity/MainActivi ...

  7. Android系统启动流程(四)Launcher进程启动过程解析(附带面试题)

    前面我们分析了init进程,zygote进程,SystemServer进程,本篇的Launcher是系统启动流程的最后一个进程. 1 Launcher概述 Launcher进程是一个系统的应用程序,位 ...

  8. Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析(1)

    在前面一篇文章浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路中,介绍了在Android系统中Binder进程间通信机 ...

  9. Android系统默认Home应用程序(Launcher)的启动过程源代码分析(2)

    Step 10.  ActivityManagerService.systemReady 这个函数是在上面的Step 6中的ServerThread.run函数在将系统中的一系列服务都初始化完毕之后才 ...

最新文章

  1. 2021CCF颁奖典礼首次多平台网络直播,致敬获得者!CCF杰出工程师
  2. django oracle数据库配置,django连接oracle时setting 配置方法
  3. sqlalchemy 使用mysql_使用SQLALchemy连接MySql数据库并进行操作
  4. web前端学习文档 电子版_web前端工程师要学习那些内容
  5. linux cpu占用100原因查询,如何根据查询异常时间节点和连接进而确定CPU使用率100%的原因...
  6. MySQL—隔离级别
  7. “约见”面试官系列之常见面试题第二十篇之vuex得理解(建议收藏)
  8. 95-10-190-启动-DynamicConfigManager
  9. java传递引用参数
  10. 养老金上涨后,退休老人每个月6500元的养老金,属于什么水平?
  11. OPENSTACK在RHEL7安装;admin创建虚拟机模板供demo使用
  12. 推荐几本书,再送66本书【包邮到家】
  13. Spring源码浅析之配置文件解析(一)
  14. CMake macOS安装
  15. 2016北大叉院、北大信科保研经历
  16. 阿里云服务器配置端口安全组完整教程大全
  17. python足球联赛赛程_足球联赛赛程表生成
  18. MJLQ2CH A java开发_新MacBook Pro的原彩显示技术是如何实现的?
  19. 全网唯一正确身份证和社统一社会信用代码自定义表单校验器(身份证校验和社统一社会信用代码校验)
  20. 华为emui11系统是鸿蒙系统吗,华为EMUI10.1才更新不久,EMUI11就被曝,网友:咋没见鸿蒙?...

热门文章

  1. 吴恩达机器学习课后作业——偏差和方差
  2. 传感器连接mysql_获取传感器数据并传入数据库-HTTP/POST/ASP.NET
  3. 每日一“酷”之Cookie
  4. 德国汉诺威地面材料展览会搭建就找上海宽创国际
  5. Auto.js Pro安卓免ROOT引流脚本开发系列教程28网易公开课(6)-取随机话术
  6. python绘制五角星
  7. Python环境下数据处理常用命令
  8. Python | 小白的 Asyncio 教程
  9. 深圳电视台小间距P2高清圆弧屏(弧形屏)是用软模组(软屏)拼成
  10. C++ Primer Plus课后编程练习第6章参考代码