一、前言

本文承接上一节:GEF入门实例_总结_03_显示菜单和工具栏

注意到app目录下的6个类文件。

这6个文件对RCP应用程序而言非常重要,可能我们现在对这几个文件的理解还是云里雾里,这一节我们将通过这几个文件来了解Eclipse插件的启动过程。

二、Eclipse工作台层次结构

1.Eclipse工作台示例

(1)运行Eclipse之后,出现下图所示界面,其中顶层窗口就是Eclipse的工作台窗口。

(2)每个工作台窗口又包括菜单栏、工具栏、状态栏 和 多个工作台页面

(3)每个工作台页面又包含多个视图、编辑器

顶层窗口就是Eclipse的工作台窗口

三、6个类文件的作用

这六个类文件的作用如下:

序号 类名 作用
1 Application RCP应用程序的入口
2 ApplicationWorkbenchAdvisor 负责应用程序生命周期管理
3 ApplicationWorkbenchWindowAdvisor 负责窗口生命周期管理。控制窗口界面的UI元素
4 ApplicationActionBarAdvisor 负责定义创建窗口的行为。 负责创建菜单栏、工具栏、状态行
5 Perspective 默认透视图,负责界面布局的安排
6 Activator 控制插件的生命周期

1.Application

package gef.tutorial.step.app;

import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI; /**
* This class controls all aspects of the application's execution
*/
public class Application implements IApplication { @Override
public Object start(IApplicationContext context) throws Exception {
Display display = PlatformUI.createDisplay();
try {
//========工作台打开之前,可做登录操作 //即将打开工作台
int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor());
if (returnCode == PlatformUI.RETURN_RESTART)
return IApplication.EXIT_RESTART;
else
return IApplication.EXIT_OK;
} finally {
display.dispose();
} } @Override
public void stop() {
if (!PlatformUI.isWorkbenchRunning())
return;
final IWorkbench workbench = PlatformUI.getWorkbench();
final Display display = workbench.getDisplay();
display.syncExec(new Runnable() {
public void run() {
if (!display.isDisposed())
workbench.close();
}
});
}
}

(1)Application类是RCP程序的入口,它实现了IApplication接口,在RCP程序启动时会执行该接口的start方法。

(2)事件循环:工作台启动之后,会处于持续打开状态。这时,应用程序开始处理用户的鼠标单击、移动、按键等各种事件,一直到用户关闭程序退出,这就是所谓的事件循环。

2.ApplicationWorkbenchAdvisor

package gef.tutorial.step.app;

import org.eclipse.ui.application.IWorkbenchConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchAdvisor;
import org.eclipse.ui.application.WorkbenchWindowAdvisor; public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor { private static final String PERSPECTIVE_ID = "gef.tutorial.step.perspective"; //$NON-NLS-1$ @Override
public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
return new ApplicationWorkbenchWindowAdvisor(configurer);
} /**1.在工作台开始运行之前执行初始化操作。
* 在打开任何窗口之前,在工作台初始化期间调用此方法。
*
*/
@Override
public void initialize(IWorkbenchConfigurer configurer) { super.initialize(configurer); //1.1 设置应用程序每次退出时保存当前窗口状态
configurer.setSaveAndRestore(true);
} /**
* 2.指定工作台的初始透视图
*/
@Override
public String getInitialWindowPerspectiveId() {
return PERSPECTIVE_ID;
}
}

(1)负责应用程序生命周期管理。

(2)可以在该类中实现程序启动或关闭时的某种处理

(3)主要方法

序号 方法名 生命周期 用法
1 initialize 最先调用。在工作台开始运行之前执行一些初始化操作。 可用来处理初始化配置操作
2 preStartup initialize之后、第一个窗口打开之前调用 可以用来处理临时或者可选处理操作
3 postStartup 第一个窗口打开之后但启动事件循环之前调用 可以用来进行那些需要自动处理的动作
4 preShutdown 事件循环结束之后但工作台关闭之前调用 可以用来进行保存数据、关闭数据库服务器等操作
5 postShutdown 工作台关闭之后调用 可以用来进行保存应用程序

3.ApplicationWorkbenchWindowAdvisor

package gef.tutorial.step.app;

import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.IActionBarConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchWindowAdvisor; public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor { public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
super(configurer);
} /**
* 1.创建一个新的action bar advisor
* 指定由ApplicationActionBarAdvisor来配置窗口的操作条。
*/
@Override
public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) {
return new ApplicationActionBarAdvisor(configurer);
} /**
* 2.在窗口打开之前执行
*/
@Override
public void preWindowOpen() {
IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
//1.设置窗口初始化大小
configurer.setInitialSize(new Point(700, 550)); //2.显示工具栏
configurer.setShowCoolBar(true); //3.不显示状态栏
configurer.setShowStatusLine(false); //4.设置窗口标题
configurer.setTitle("GEF入门实例"); //$NON-NLS-1$
}
}

(1)负责应用程序窗口生命周期管理。

(2)该类扩展自WorkbenchWindowAdvisor。每个应用程序都需要一个WorkbenchWindowAdvisor 来控制窗口界面的UI元素。

开发人员可以控制窗口创建时(或其他生命周期时)的大小、标题、位置等。

(3)主要方法

序号 方法名 生命周期 用法
1 preWindowOpen 窗口控件创建之前调用 可用于设置窗口的初始大小、状态栏、工具栏等的可视性
2 postWindowRestore 当窗口根据上一次的保存状态恢复创建之后调用 可用于调整窗口的恢复状态
3 postWindowCreate 窗口创建之后调用 可用于调整窗口
4 postWindowOpen 窗口已经打开之后调用 可用于注册窗口监听,例如在此方法中实现系统托盘

4.ApplicationActionBarAdvisor

package gef.tutorial.step.app;

import org.eclipse.jface.action.ICoolBarManager;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.swt.SWT;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.IActionBarConfigurer; import gef.tutorial.step.action.DiagramAction; public class ApplicationActionBarAdvisor extends ActionBarAdvisor { private IWorkbenchAction exitAction;
private IWorkbenchAction aboutAction;
private DiagramAction diagramAction; public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) {
super(configurer);
} /**
* 1.注册菜单或者工具栏的Action。Action只有注册后才能添加到菜单中。
*
*/
@Override
protected void makeActions(IWorkbenchWindow window) {
//退出
exitAction = ActionFactory.QUIT.create(window);
register(exitAction); //关于
aboutAction = ActionFactory.ABOUT.create(window);
register(aboutAction); //绘图
diagramAction = new DiagramAction(window);
register(diagramAction); } /**
* 2.填充菜单栏。用Action来填充菜单
*
* (1) 菜单管理器负责管理菜单项、设置菜单行为、创建级联菜单或者对菜单项进行分组。
* (2) MenuManager构造函数:菜单项文本、菜单项ID
* (3) new Separator() 为一条分割线
*/
@Override
protected void fillMenuBar(IMenuManager menuBar) {
//(1)一级菜单 File
MenuManager fileMenuManager= new MenuManager("File", "fileMenuManager");
//加入绘图动作,是叶子节点菜单,也是二级菜单。点击之后将执行Action的run方法
fileMenuManager.add(diagramAction);
//加入分隔符
fileMenuManager.add(new Separator());
//加入退出动作
fileMenuManager.add(exitAction); //(2)一级菜单 Help
MenuManager helpMenuManager = new MenuManager("Help", "helpMenuManager");
helpMenuManager.add(aboutAction);
//加入二级菜单
helpMenuManager.add(fileMenuManager); //(3)将菜单加入菜单栏
menuBar.add(fileMenuManager);
menuBar.add(helpMenuManager); } /**
* 3.填充工具栏。用Action来填充工具栏
* (1) 工具栏默认是不显示。在 ApplicationWorkbenchWindowAdvisor 类中的
* preWindowOpen方法中有一句 configurer.setShowCoolBar(false);将false改为true即可显示工具栏
* (2) 工具栏管理器负责工具栏的分类管理
* (3) SWT.FLAT将工具栏设置成平滑方式,SWT.SHADOW_OUT用于在工具栏和菜单栏之间加一条分割线
*
*/
@Override
protected void fillCoolBar(ICoolBarManager coolBar) {
//1.生成工具栏
ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT | SWT.SHADOW_OUT); //2.将工具放入工具栏
toolBarManager.add(diagramAction); //3.将工具栏放入
coolBar.add(toolBarManager);
} }

(1)负责定义创建窗口的行为。

(2)该类扩展自ActionBarAdvisor,用于创建菜单栏、工具栏、状态行

(3)主要方法

序号 方法名 用法
1 makeActions 注册菜单或者工具栏的工作
2 fillMenuBar 添加菜单栏
3 fillCoolBar 添加工具栏
4 fillStatusLine 添加状态栏

5.Perspective

package gef.tutorial.step.app;

import org.eclipse.ui.IFolderLayout;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory; public class Perspective implements IPerspectiveFactory { public void createInitialLayout(IPageLayout layout) {
//一、基本配置
//1.1 获取布局的编辑器
final String editorArea = layout.getEditorArea();
//1.2 设置显示编辑区
layout.setEditorAreaVisible(true); //二、添加各种视图
//2.1 添加属性视图
IFolderLayout bottomFolder = layout.createFolder("bottom",IPageLayout.BOTTOM, 0.75f, editorArea);
bottomFolder.addView(IPageLayout.ID_PROP_SHEET); //2.2 添加大纲视图
IFolderLayout rightBottomFolder = layout.createFolder("right",IPageLayout.RIGHT, 0.75f, editorArea);
rightBottomFolder.addView(IPageLayout.ID_OUTLINE); }
}

(1)是程序默认的透视图

(2)负责初始页面布局并显示

(3)主要方法

方法名 用法
createInitialLayout

创建页面的初始布局。此方法的实现人员可以向透视图添加其他视图。

6.Activator

package gef.tutorial.step.app;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext; /**
* The activator class controls the plug-in life cycle
*/
public class Activator extends AbstractUIPlugin { // The plug-in ID
public static final String PLUGIN_ID = "gef.tutorial.step"; //$NON-NLS-1$ // The shared instance
private static Activator plugin; /**
* The constructor
*/
public Activator() {
} /*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
} /*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
plugin = null;
super.stop(context);
} /**
* Returns the shared instance
*
* @return the shared instance
*/
public static Activator getDefault() {
return plugin;
} /**
* Returns an image descriptor for the image file at the given
* plug-in relative path
*
* @param path the path
* @return the image descriptor
*/
public static ImageDescriptor getImageDescriptor(String path) {
return imageDescriptorFromPlugin(PLUGIN_ID, path);
}
}

(1)是插件类,控制插件的生命周期

(2)见第二节: GEF入门实例_总结_02_新建初始RCP空项目   ,如下图,

若2处勾选 "This plug-in will make contributions to the UI",表示插件对UI进行添加,则此类将扩展自AbstractUIPlugin。

否则,该类扩展自 AbstractUIPlugin 的父类 Plugin。

(3)主要方法

序号 方法名 作用
1 start 插件启动时的处理
2 stop 插件停止时的处理
3 getDefault 获取默认的插件类实例。单例模式。
4 getImageDescriptor 根据插件相对路径返回图片描述符,可用于获取图片

四、Eclipse插件启动流程图

有问题的地方:第9步的实际的具体流程我暂时还不清楚。

Eclipse启动流程图如下,都是自己总结的,所以可能有不当之处,希望读者能解惑并将其完善。

温馨提示:可将下图拖入浏览器中查看原图

五、Eclipse插件启动流程分析

以下流程与上述流程图步骤对应,通过进行断点调试,可发现启动流程如下:

0.run

首先是运行插件,可参见: GEF入门实例_总结_02_新建初始RCP空项目  的 “三、启动项目” 部分。

(1)其中注意上图:run  an  application  ,这里主要是设置程序的入口,这里我们选择的是 “gef.tutorial.step.application”,含义为(插件ID).(扩展点 runtime.applications 的ID)。

(2)打开plugin.xml,在overview页,可以看到插件id为gef.tutorial.step

(3)在 Extensions 页,可以看到扩展点“org.eclipse.core.runtime.applications”的 ID 为 application。

(4)至此,我们知道插件启动时,执行这个扩展点,那为啥会执行到Application类中去呢?如下图:

1.插件启动

Application.start

如上所述,因为Run Configuration  中 run an application 配置的入口程序为 Application 类,因此程序启动时,会执行到 Application 的 start 方法中来。

    int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor());

然后由此处代码创建一个 ApplicationWorkbenchAdvisor ,并进行到第二步

2.获取工作台窗口初始透视标识

ApplicationWorkbenchAdvisor.getInitialWindowPerspectiveId

/**
* 2.指定工作台的初始透视图
*/
@Override
public String getInitialWindowPerspectiveId() {
return PERSPECTIVE_ID;
}

3.创建workbench window advisor

ApplicationWorkbenchAdvisor.createWorkbenchWindowAdvisor

@Override
public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
return new ApplicationWorkbenchWindowAdvisor(configurer);
}

在这一步去创建了  ApplicationWorkbenchWindowAdvisor  ,通过这个Advisor 可以配置工作台窗口。

4.窗口打开前的处理

ApplicationWorkbenchWindowAdvisor.preWindowOpen

/**
* 2.在窗口打开之前执行
*/
@Override
public void preWindowOpen() {
IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
//1.设置窗口初始化大小
configurer.setInitialSize(new Point(700, 550)); //2.显示工具栏
configurer.setShowCoolBar(true); //3.不显示状态栏
configurer.setShowStatusLine(false); //4.设置窗口标题
configurer.setTitle("GEF入门实例"); //$NON-NLS-1$
}

在窗口打开前,设置了窗口大小、标题、工具栏与状态栏的可视性

5.创建 ActionBarAdvisor

ApplicationWorkbenchWindowAdvisor.createActionBarAdvisor

    /**
* 1.创建一个新的action bar advisor
* 指定由ApplicationActionBarAdvisor来配置窗口的操作条。
*/
@Override
public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) {
return new ApplicationActionBarAdvisor(configurer);
}

6.注册菜单或者工具栏的Action

ApplicationActionBarAdvisor.makeActions

    /**
* 1.注册菜单或者工具栏的Action。Action只有注册后才能添加到菜单中。
*
*/
@Override
protected void makeActions(IWorkbenchWindow window) {
//退出
exitAction = ActionFactory.QUIT.create(window);
register(exitAction); //关于
aboutAction = ActionFactory.ABOUT.create(window);
register(aboutAction); //绘图
diagramAction = new DiagramAction(window);
register(diagramAction); }

7.填充菜单栏

ApplicationActionBarAdvisor.fillMenuBar

    /**
* 2.填充菜单栏。用Action来填充菜单
*
* (1) 菜单管理器负责管理菜单项、设置菜单行为、创建级联菜单或者对菜单项进行分组。
* (2) MenuManager构造函数:菜单项文本、菜单项ID
* (3) new Separator() 为一条分割线
*/
@Override
protected void fillMenuBar(IMenuManager menuBar) {
//(1)一级菜单 File
MenuManager fileMenuManager= new MenuManager("File", "fileMenuManager");
//加入绘图动作,是叶子节点菜单,也是二级菜单。点击之后将执行Action的run方法
fileMenuManager.add(diagramAction);
//加入分隔符
fileMenuManager.add(new Separator());
//加入退出动作
fileMenuManager.add(exitAction); //(2)一级菜单 Help
MenuManager helpMenuManager = new MenuManager("Help", "helpMenuManager");
helpMenuManager.add(aboutAction);
//加入二级菜单
helpMenuManager.add(fileMenuManager); //(3)将菜单加入菜单栏
menuBar.add(fileMenuManager);
menuBar.add(helpMenuManager); }

8.填充工具栏

ApplicationActionBarAdvisor.fillCoolBar

/**
* 3.填充工具栏。用Action来填充工具栏
* (1) 工具栏默认是不显示。在 ApplicationWorkbenchWindowAdvisor 类中的
* preWindowOpen方法中有一句 configurer.setShowCoolBar(false);将false改为true即可显示工具栏
* (2) 工具栏管理器负责工具栏的分类管理
* (3) SWT.FLAT将工具栏设置成平滑方式,SWT.SHADOW_OUT用于在工具栏和菜单栏之间加一条分割线
*
*/
@Override
protected void fillCoolBar(ICoolBarManager coolBar) {
//1.生成工具栏
ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT | SWT.SHADOW_OUT); //2.将工具放入工具栏
toolBarManager.add(diagramAction); //3.将工具栏放入
coolBar.add(toolBarManager);
}

9.getInitialWindowPerspectiveId(有疑问)

ApplicationWorkbenchAdvisor.getInitialWindowPerspectiveId

    /**
* 2.指定工作台的初始透视图
*/
@Override
public String getInitialWindowPerspectiveId() {
return PERSPECTIVE_ID;
}

断点调试时是又走了一遍此方法,

至于为啥走了两遍,怎么走到第10步的,这个还不清楚。

希望读者能为我解惑,不胜感激。

10.创建默认透视图的初始布局

Perspective.createInitialLayout

package gef.tutorial.step.app;

import org.eclipse.ui.IFolderLayout;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory; public class Perspective implements IPerspectiveFactory { public void createInitialLayout(IPageLayout layout) {
//一、基本配置
//1.1 获取布局的编辑器
final String editorArea = layout.getEditorArea();
//1.2 设置显示编辑区
layout.setEditorAreaVisible(true); //二、添加各种视图
//2.1 添加属性视图
IFolderLayout bottomFolder = layout.createFolder("bottom",IPageLayout.BOTTOM, 0.75f, editorArea);
bottomFolder.addView(IPageLayout.ID_PROP_SHEET); //2.2 添加大纲视图
IFolderLayout rightBottomFolder = layout.createFolder("right",IPageLayout.RIGHT, 0.75f, editorArea);
rightBottomFolder.addView(IPageLayout.ID_OUTLINE); }
}

在这一步创建工作台默认透视图的初始布局,可在此方法中添加其他视图。

这样窗口就创建好了

11.窗口创建之后

ApplicationWorkbenchWindowAdvisor.postWindowCreate

在窗口创建完毕之后,会执行此方法。可用此方法来调整窗口

六、参考资料

1.《Eclipse RCP 应用系统开发方法与实践》

2.《Eclipse插件开发学习笔记》

3.本系列总结配套PDF教程《GEF开发简单实例.pdf》

GEF入门实例_总结_04_Eclipse插件启动流程分析的更多相关文章

  1. GEF入门实例_总结_05_显示一个空白编辑器

    一.前言 本文承接上一节:GEF入门实例_总结_04_Eclipse插件启动流程分析 在第三节( GEF入门实例_总结_03_显示菜单和工具栏  ),我们创建了菜单和工具栏. 这一节,我们来实现:点击 ...

  2. GEF入门实例_总结_02_新建初始RCP空项目

    一.前言 本节承接上一节: GEF入门实例_总结_01_教程.源码.开发环境准备 这一节我们来创建一个空的RCP项目. 二.新建RCP项目 1. New 一个 Plug-in Project 2.输入 ...

  3. GEF入门实例_总结_06_为编辑器添加内容

    一.前言 本文承接上一节:GEF入门实例_总结_05_显示一个空白编辑器 在上一节我们为我们的插件添加了一个空白的编辑器,这一节我们将为此编辑器添加内容. 二.GEF的MVC模式 在此只简单总结一下, ...

  4. GEF入门实例_总结_03_显示菜单和工具栏

    一.前言 本文承接上一节: GEF入门实例_总结_02_新建初始RCP空项目 这一节,我们来给我们的插件加上菜单. 二.基础知识 1.action bar.menubar.coolbar   含义 a ...

  5. GEF入门实例_总结_01_教程、源码、开发环境准备

    一.前言 最近在学Eclipse插件开发,发现了一个比较好的GEF入门教程,并且按照教程上的操作,一步步实现了一个入门Demo,在此感谢作者的贡献. 好记性不如烂笔头,故决定总结一下这段时间的学习心得 ...

  6. u-boot启动流程分析(2)_板级(board)部分

    转自:http://www.wowotech.net/u-boot/boot_flow_2.html 目录: 1. 前言 2. Generic Board 3. _main 4. global dat ...

  7. u-boot启动流程分析(1)_平台相关部分

    转自:http://www.wowotech.net/u-boot/boot_flow_1.html 1. 前言 本文将结合u-boot的“board—>machine—>arch—> ...

  8. Netty 拆包粘包和服务启动流程分析

    Netty 拆包粘包和服务启动流程分析 通过本章学习,笔者希望你能掌握EventLoopGroup的工作流程,ServerBootstrap的启动流程,ChannelPipeline是如何操作管理Ch ...

  9. 【转】Netty 拆包粘包和服务启动流程分析

    原文:https://www.cnblogs.com/itdragon/archive/2018/01/29/8365694.html Netty 拆包粘包和服务启动流程分析 通过本章学习,笔者希望你 ...

随机推荐

  1. 0405-服务注册与发现-客户端负载均衡-Ribbon 同Eureka使用,Ribbon脱离Eureka使用

    一.Ribbon 同Eureka使用,注意事项 前几节一同使用,注意事项: 如果没有其他区域数据源,则根据客户端配置进行猜测(与实例配置相反).能够获取eureka.client.availabili ...

  2. 剑指offer 面试61题

    面试61题: 题目:LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到 ...

  3. XML文件结构和基本语法

    XML文件的结构性内容,包括节点关系以及属性内容等等.元素是组成XML的最基本的单位,它由开始标记,属性和结束标记组成.就是一个元素的例子,每个元素必须有一个元素名,元素可以若干个属性以及属性值. x ...

  4. Raspberry Pi开发之旅-发送邮件记录时间及IP

    由于我使用树莓派的场景大多数是在没有显示器.只用terminal连接它的情况下,所以,它的IP地址有时会在重启之后变掉(DHCP的),导致我无法通过terminal连接上它.然后我又要很麻烦地登录路由 ...

  5. RTC是DS1339,驱动采用的是rtc-ds1307.c

    我的外部RTC是DS1339,驱动采用的是rtc-ds1307.c在内核里选上了 <*> I2C support 以及 [*]   Set system time from RTC on  ...

  6. 蓝牙固件升级(OTA升级)原理设计

    转:http://blog.csdn.net/yueqian_scut/article/details/50849033 固件空中升级(OTA)与固件二次引导的原理和设计 原创 2016年03月10日 ...

  7. php数组函数-array_flip()

    array_flip()函数返回一个反转后的数组,如果同一个值出现多次,则最 后一个键名作为它的值,所有其他的键名将丢失. 如果原数组中的值得数据类型不是字符串或整数,函数将报错. array_fli ...

  8. IDEA使用前的各种基本设置(转)

    先搞个链接,以后自己慢慢总结:传送门

  9. Android系统--Binder系统具体框架分析(一)

    Binder系统具体框架分析(一) 一.Binder系统核心框架 1. IPC:Inter-Process Communication, 进程间通信 A进程将数据原原本本发送B进程,主要负责进程间数据 ...

  10. Loop through an array in JavaScript

    https://stackoverflow.com/questions/3010840/loop-through-an-array-in-javascript?page=1&tab=votes ...