Appium Java client has facilities which components to Page Object design pattern and Selenium PageFactory.//appium的java客户端支持PageObject和PageFactory。读本文之前一定要有PageObject和PageFactory的概念。

原文地址:https://github.com/appium/java-client/blob/master/docs/Page-objects.md#specification

//第一部分:讲解声明filed时,如何使用注解

WebElement/list of WebElement field can be populated by default:

//对于WebElement使用@Findby注解,元素类型是WebElement。
 import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
... @FindBy(someStrategy) //for browser or web view html UI
//also for mobile native applications when other locator strategies are not defined
WebElement someElement; @FindBy(someStrategy) //for browser or web view html UI
//also for mobile native applications when other locator strategies are not defined
List<WebElement> someElements;

If there is need to use convinient locators for mobile native applications then the following is available:

//对于移动端原生应用,分别使用@AndroidFindBy@SelendroidFindBy@iOSFindBy注解,元素类型分别为AndroidElement、RemoteWebElement、IOSElement。

 import io.appium.java_client.android.AndroidElement;
import org.openqa.selenium.remote.RemoteWebElement;
import io.appium.java_client.pagefactory.*;
import io.appium.java_client.ios.IOSElement; @AndroidFindBy(someStrategy) //for Android UI when Android UI automator is used
AndroidElement someElement; @AndroidFindBy(someStrategy) //for Android UI when Android UI automator is used
List<AndroidElement> someElements; @SelendroidFindBy(someStrategy) //for Android UI when Selendroid automation is used
RemoteWebElement someElement; @SelendroidFindBy(someStrategy) //for Android UI when Selendroid automation is used
List<RemoteWebElement> someElements; @iOSFindBy(someStrategy) //for iOS native UI
IOSElement someElement; @iOSFindBy(someStrategy) //for iOS native UI
List<IOSElement> someElements;

The example for the crossplatform mobile native testing

//跨平台时,同时使用@AndroidFindBy@iOSFindBy注解,元素类型为MobileElement。

 import io.appium.java_client.MobileElement;
import io.appium.java_client.pagefactory.*; @AndroidFindBy(someStrategy)
@iOSFindBy(someStrategy)
MobileElement someElement; @AndroidFindBy(someStrategy) //for the crossplatform mobile native
@iOSFindBy(someStrategy) //testing
List<MobileElement> someElements;

The fully cross platform examle

//全平台时,同时使用@FindBy@AndroidFindBy@iOSFindBy注解,元素类型为RemoteWebElement。

 import org.openqa.selenium.remote.RemoteWebElement;
import io.appium.java_client.pagefactory.*;
import org.openqa.selenium.support.FindBy; //the fully cross platform examle
@FindBy(someStrategy) //for browser or web view html UI
@AndroidFindBy(someStrategy) //for Android native UI
@iOSFindBy(someStrategy) //for iOS native UI
RemoteWebElement someElement; //the fully cross platform examle
@FindBy(someStrategy)
@AndroidFindBy(someStrategy) //for Android native UI
@iOSFindBy(someStrategy) //for iOS native UI
List<RemoteWebElement> someElements;

Also it is possible to define chained or any possible locators.

//chained是指使用@FindBys、@AndroidFindBys、@iOSFindBys注解。修饰列表变量时,列表的内容是多个定位方法找到的元素。修饰非列表变量时,变量值是什么呢?

- Chained

If you use build versions < 5.x.x

 import org.openqa.selenium.remote.RemoteWebElement;
import io.appium.java_client.pagefactory.*;
import org.openqa.selenium.support.FindBys;
import org.openqa.selenium.support.FindBy; @FindBys({@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindBys({@AndroidFindBy(someStrategy1), @AndroidFindBy(someStrategy2)})
@iOSFindBys({@iOSFindBy(someStrategy1), @iOSFindBy(someStrategy2)})
RemoteWebElement someElement; @FindBys({@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindBys({@AndroidFindBy(someStrategy1), @AndroidFindBy(someStrategy2)})
@iOSFindBys({@iOSFindBy(someStrategy1), @iOSFindBy(someStrategy2)})
List<RemoteWebElement> someElements;

If you use build versions >= 5.x.x

 import org.openqa.selenium.remote.RemoteWebElement;
import io.appium.java_client.pagefactory.*;
import org.openqa.selenium.support.FindBys;
import org.openqa.selenium.support.FindBy; @FindBys({@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)
@iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
RemoteWebElement someElement; @FindBys({@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)
@iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
List<RemoteWebElement> someElements;

or

 import org.openqa.selenium.remote.RemoteWebElement;
import io.appium.java_client.pagefactory.*;
import org.openqa.selenium.support.FindBys;
import org.openqa.selenium.support.FindBy; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.CHAIN; @HowToUseLocators(androidAutomation = CHAIN, iOSAutomation = CHAIN)
@FindBys({@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)
@iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
RemoteWebElement someElement; @HowToUseLocators(androidAutomation = CHAIN, iOSAutomation = CHAIN)
@FindBys({@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)
@iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
List<RemoteWebElement> someElements;

//possible是指使用@FindAll@AndroidFindAll@iOSFindAll注解。如果修饰列表变量,那么列表的内容是由全部声明的定位方法找到的元素。如果修饰非列表变量,那么变量值是第一个被找到的元素,无论是使用哪个已声明的定位方法。

- Any possible

If you use build versions < 5.x.x

 import org.openqa.selenium.remote.RemoteWebElement;
import io.appium.java_client.pagefactory.*;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.FindByAll; @FindAll({@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindAll({@AndroidFindBy(someStrategy1), @AndroidFindBy(someStrategy2)})
@iOSFindAll({@iOSFindBy(someStrategy1), @iOSFindBy(someStrategy2)})
RemoteWebElement someElement; @FindAll({@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindAll({@AndroidFindBy(someStrategy1), @AndroidFindBy(someStrategy2)})
@iOSFindAll({@iOSFindBy(someStrategy1), @iOSFindBy(someStrategy2)})
List<RemoteWebElement> someElements;

If you use build versions >= 5.x.x

 import org.openqa.selenium.remote.RemoteWebElement;
import io.appium.java_client.pagefactory.*;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.FindByAll; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; @HowToUseLocators(androidAutomation = ALL_POSSIBLE, iOSAutomation = ALL_POSSIBLE)
@FindAll{@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)
@iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
RemoteWebElement someElement; @HowToUseLocators(androidAutomation = ALL_POSSIBLE, iOSAutomation = ALL_POSSIBLE)
@FindAll({@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)
@iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
List<RemoteWebElement> someElements;

Also possible combined variants:

 import org.openqa.selenium.remote.RemoteWebElement;
import io.appium.java_client.pagefactory.*;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.FindByAll; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.CHAIN;
import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; @HowToUseLocators(androidAutomation = CHAIN, iOSAutomation = ALL_POSSIBLE)
@FindAll{@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)
@iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
RemoteWebElement someElement; @HowToUseLocators(androidAutomation = CHAIN, iOSAutomation = ALL_POSSIBLE)
@FindAll({@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2)
@iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
List<RemoteWebElement> someElements;

or

 import org.openqa.selenium.remote.RemoteWebElement;
import io.appium.java_client.pagefactory.*;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.FindByAll; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; @HowToUseLocators(iOSAutomation = ALL_POSSIBLE)
@FindAll{@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2) //this is the chain
//by default
@iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
RemoteWebElement someElement; @HowToUseLocators(iOSAutomation = ALL_POSSIBLE)
@FindAll({@FindBy(someStrategy1), @FindBy(someStrategy2)})
@AndroidFindBy(someStrategy1) @AndroidFindBy(someStrategy2) //this is the chain
//by default
@iOSFindBy(someStrategy1) @iOSFindBy(someStrategy2)
List<RemoteWebElement> someElements;

//第二部分:讲解如何使用PageFactory初始化field。

Appium Java client is integrated with Selenium PageFactory by AppiumFieldDecorator.

Object fields are populated as below://按照这个方式初始化。

 import io.appium.java_client.pagefactory.*;
import org.openqa.selenium.support.PageFactory; PageFactory.initElements(new AppiumFieldDecorator(searchContext
/*searchContext is a WebDriver or WebElement
instance */),
pageObject //an instance of PageObject.class
);

//初始化时,可以设置元素定位的超时时间。

 import io.appium.java_client.pagefactory.*;
import org.openqa.selenium.support.PageFactory;
import java.util.concurrent.TimeUnit; PageFactory.initElements(new AppiumFieldDecorator(searchContext,
/*searchContext is a WebDriver or WebElement
instance */
15, //default implicit waiting timeout for all strategies//效果为:至少用15个时间单位查找元素。
TimeUnit.SECONDS),
pageObject //an instance of PageObject.class
);
import io.appium.java_client.pagefactory.*;
import org.openqa.selenium.support.PageFactory;
import java.util.concurrent.TimeUnit; PageFactory.initElements(new AppiumFieldDecorator(searchContext,
/*searchContext is a WebDriver or WebElement
instance */
new TimeOutDuration(15, //default implicit waiting timeout for all strategies
TimeUnit.SECONDS)), //效果为:至少用15个时间单位查找元素。

 pageObject //an instance of PageObject.class  );

If time of the waiting for elements differs from usual (longer, or shorter when element is needed only for quick checkings/assertions) then//还可以为每个元素单独设置超时时间。

 import io.appium.java_client.pagefactory.*;

 @WithTimeout(timeOut = yourTime, timeUnit = yourTimeUnit)
RemoteWebElement someElement; @WithTimeout(timeOut = yourTime, timeUnit = yourTimeUnit)
List<RemoteWebElement> someElements;

//第三部分:讲解一个例子。

The additional feature.

The simple example

Let's imagine that the task is to check an Android client of the http://www.rottentomatoes.com. Let it be like a picture below

Lets imagine that it is only a part of the screen.

A typical page object could look like://典型的page object的写法

 public class RottenTomatoesScreen {
//convinient locator
private List<AndroidElement> titles; //convinient locator
private List<AndroidElement> scores; //convinient locator
private List<AndroidElement> castings;
//element declaration goes on public String getMovieCount(){
//.......
} public String getTitle(params){
//.......
} public String getScore(params){
//.......
} public String getCasting(params){
//.......
} public void openMovieInfo(params){
//.......
} //method declaration goes on
}

The description above can be decomposed. Let's work it out!//上面的PageObject写法,可以进行拆解。

Firstly a Movie-widget could be described this way://首先,定义一个widget:猜测是页面上的一个对象,假设烂番茄网站上也有电视剧、动画片的信息,而这两者又有不同的介绍,比如电视剧有演员信息,动画片有配音人员和设计师的信息,那么电视剧和动画可以看做是两个不同的widget。

 import io.appium.java_client.pagefactory.Widget;
import org.openqa.selenium.WebElement; public class Movie extends Widget{
protected Movie(WebElement element) {
super(element);
} //convinient locator //大多时候,不同movie的具有相同的id或者classname,这时候用id或者classname就可以定位全部的movie。同理,不同movie的title也都有相同的id或者classname,一个定位字符串可以通用与全部的title。
private AndroidElement title; //convinient locator
private AndroidElement score; //convinient locator
private AndroidElement casting; public String getTitle(params){
//.......
} public String getScore(params){
//.......
} public String getCasting(params){
//.......
} public void openMovieInfo(params){
((AndroidElement) getWrappedElement()).tap(1, 1500);
} }

So, now page object looks

 public class RottenTomatoesScreen {

      @AndroidFindBy(a locator which convinient to find a single movie-root - element)//不同movie具有相同的id或者classname,这时候一个定位字符串可以通用于全部的movie。
private List<Movie> movies; //element declaration goes on public String getMovieCount(){
return movies.size();
} public Movie getMovie(int index){
//any interaction with sub-elements of a movie-element
//will be performed outside of the page-object instance
return movie.get(index);
}
//method declaration goes on
}

Ok. What if Movie-class is reused and a wrapped root element is usually found by the same locator?

Then//如果需要使用movie类生成多个实例,而且这些实例使用同一个定位字符串,那么可以将实例的注解移到定义movie类的代码前面。

 //the class is annotated !!!
@AndroidFindBy(a locator which convinient to find a single movie-root - element)
public class Movie extends Widget{
...
}

and

 public class RottenTomatoesScreen {
//!!! locator is not necessary at this case
private List<Movie> movies;
...
}

Ok. What if movie list is not a whole screen? E.g. we want to describe it as a widget with nested movies.

Then://这里是说,如何生成一个特殊的widget,它的内部元素还是widget。假设当前页面是一个内容非常丰富的页面,有电影、电视剧、综艺节目相关的信息,电影分类内部的每个电影都有名字、得分、剧情简介等信息,电视剧和综艺节目也有各自的内部信息。此时,每部电影都是一个小的widget,电影类别则是一个大的widget,整个页面由电影、电视剧、综艺节目三个大的widget组成。注解的使用方法同前面一样。

 //with the usual locator or without it
public class Movies extends Widget{ //with a custom locator or without it
private List<Movie> movies;
...
}

and

 public class RottenTomatoesScreen {

     //with a custom locator or without it
Movies movies;
...
}

Good! How to poputate all these fields?

As usual:

 RottenTomatoesScreen screen = new RottenTomatoesScreen();
PageFactory.initElements(new AppiumFieldDecorator(searchContext /*WebDriver or WebElement
instance */), screen);

//第四部分:说明

Specification

A class which describes a widget or group of elements should extend//要想使用widget,必须要继承widget类。

io.appium.java_client.pagefactory.Widget;

Any widget/group of elements can be described it terms of sub-elements or nested sub-widgets.
Appium-specific annotations are used for this purpose.

Any class which describes the real widget or group of elements can be annotated

That means that when the same "widget" is used frequently and any root element of this can be found by the same locator then user can

 @FindBy(relevant locator) //how to find a root element//假设UsersWidget对应于实际页面的movie,那么这个定位字符串是能够匹配全部movie的通用的字符串。
public class UsersWidget extends Widget{ @FindBy(relevant locator) //this element will be found //同理,这里的定位字符串也必须是通用的匹配全部subElement1的字符串。
//using the root element
WebElement subElement1; @FindBy(relevant locator) //this element will be found
//using the root element
WebElement subElement2; @FindBy(relevant locator) //a root element
//of this widget is the sub-element which
//will be found from top-element
UsersWidget subWidget; //and so on..
}

and then it is enough

   //above is the other field declaration

   UsersWidget widget;

   //below is the other field/method declaration

If the widget really should be found using an another locator then

   //above is the other field declaration
@FindBy(another relevant locator) //this locator overrides //这里的定位字符串可以覆盖声明类时使用的定位字符串。
//the declared in the using class
UsersWidget widget; //below is the other field/method declaration

Ok. What should users do if they want to implement a subclass which describes a similar group of elements for the same platform?

There is nothing special.//子类继承父类没有特殊的操作。

 @FindBy(relevant locator) //how to find a root element
public class UsersWidget extends Widget{
...
}
//at this case the root element will be found by the locator
//which is declared in superclass
public class UsersOverriddenWidget extends UsersWidget {
...
}

and

 @FindBy(relevant locator2) //this locator overrides
//all locators declared in superclasses
public class UsersOverriddenWidget2 extends UsersWidget {
...
}

Is it possible to reuse "widgets" in crossplatform testing?

If there is no special details of interaction with an application browser version and/or versions for different mobile OS's then

 @FindBy(relevant locator for browser/webview html or by default)
@AndroidFindBy(relevant locator for Android UI automator)
@iOSFindBy(relevant locator for iOS UI automation)
public class UsersWidget extends Widget { @FindBy(relevant locator for browser/webview html or by default)
@AndroidFindBy(relevant locator for Android UI automator)
@iOSFindBy(relevant locator for iOS UI automation)
RemoteWebElement subElement1; @FindBy(relevant locator for browser/webview html or by default)
@AndroidFindBy(relevant locator for Android UI automator)
@iOSFindBy(relevant locator for iOS UI automation)
RemoteWebElement subElement2; //overrides a html/default
//locator declared in the used class
@FindBy(relevant locator for browser/webview html or by default)
//overrides an Android UI automator
//locator declared in the used class
@AndroidFindBy(relevant locator for Android UI automator)
//overrides an iOS UI automation
//locator declared in the using class
@iOSFindBy(relevant locator for iOS UI automation)
UsersWidget subWidget; //and so on..
}

What if interaction with a "widget" has special details for each used platform, but the same at high-level

Then it is possible

 public /*abstract*/ class DefaultAbstractUsersWidget extends Widget{

 }

and

 @FindBy(locator)
public class UsersWidgetForHtml extends DefaultAbstractUsersWidget { }

and

 @AndroidFindBy(locator)
public class UsersWidgetForAndroid extends DefaultAbstractUsersWidget { }

and even

 @iOSFindBy(locator)
public class UsersWidgetForIOS extends DefaultAbstractUsersWidget { }

and then

   import io.appium.java_client.pagefactory.OverrideWidget;
... //above is the other field declaration
@OverrideWidget(html = UsersWidgetForHtml.class,
androidUIAutomator = UsersWidgetForAndroid.class,
iOSUIAutomation = UsersWidgetForIOS .class)
DefaultAbstractUsersWidget widget; //below is the other field/method declaration

This use case has some restrictions;

  • All classes which are declared by the OverrideWidget annotation should be subclasses of the class declared by field

  • All classes which are declared by the OverrideWidget should not be abstract. If a declared class is overriden partially like

   //above is the other field declaration

   @OverrideWidget(iOSUIAutomation = UsersWidgetForIOS .class)
DefaultUsersWidget widget; //lets assume that there are differences of
//interaction with iOS and by default we use DefaultUsersWidget.
//Then DefaultUsersWidget should not be abstract too.
// //below is the other field/method declaration
  • for now it is not possible to
   import io.appium.java_client.pagefactory.OverrideWidget;
... //above is the other field declaration
@OverrideWidget(html = UsersWidgetForHtml.class,
androidUIAutomator = UsersWidgetForAndroid.class,
iOSUIAutomation = UsersWidgetForIOS .class)
DefaultAbstractUsersWidget widget; //below is the other field/method declaration //user's code
((UsersWidgetForAndroid) widget).doSpecialWorkForAndroing()

The workaround:

   import io.appium.java_client.pagefactory.OverrideWidget;
... //above is the other field declaration
@OverrideWidget(html = UsersWidgetForHtml.class,
androidUIAutomator = UsersWidgetForAndroid.class,
iOSUIAutomation = UsersWidgetForIOS .class)
DefaultAbstractUsersWidget widget; //below is the other field/method declaration //user's code
((UsersWidgetForAndroid) widget.getSelfReference()).doSpecialWorkForAndroing()

Good! What about widget lists?

All that has been mentioned above is true for "widget" lists.

One more restriction

It is strongly recommended to implement each subclass of io.appium.java_client.pagefactory.Widget with this constructor

    public /*or any other available modifier*/ WidgetSubclass(WebElement element) {
super(element);
}

appium():PageObject&PageFactory的更多相关文章

  1. Appium PageObject

    原文地址http://blog.csdn.net/TalorSwfit20111208/article/details/77434950 由于无法联系上您,在此分享您的文章,希望谅解! Appium ...

  2. PageObject&PageFactory

    几篇介绍PageObject&PageFactory文章: PageFactory: http://code.google.com/p/selenium/wiki/PageFactory Pa ...

  3. 记我的第二次自动化尝试——selenium+pageobject+pagefactory实现自动化下单、退款、撤销回归测试

    需求: 系统需要做下单.退款.撤销的回归测试,有下单页面,所以就想到用selenium做WEB UI 自动化 项目目录结构: common包上放通用的工具类方法和浏览器操作方法 pageobject包 ...

  4. Appium使用PageFactory初始化对象时报空指针错误

    自己的测试框架里面,每个app页面都要初始化appium field,所以想到使用一个静态的变量,后来初始化一个页面对象时总是报空指针. 在网上找了好多材料,看着没有什么区别.后来在github上面看 ...

  5. Selenium的PageFactory & PageObject 在大型项目中的应用

    因为最近遇到的技术问题一直没找到可行的解决办法,一直在翻看selenium的源代码,之前写测试代码的时候就是拿来即用,写什么功能啊,就按手动的操作步骤去转换,近日看到一个文章,又去wiki上查了查,觉 ...

  6. Selenium的PageFactory在大型项目中的应用

    出路出路,走出去了,总是会有路的:困难苦难,困在家里就是难. 因为最近遇到的技术问题一直没找到可行的解决办法,一直在翻看selenium的源代码,之前写测试代码的时候就是拿来即用,写什么功能啊,就按手 ...

  7. appium()-java-client-api

    //appium java-client-api 介绍 原文地址:http://appium.github.io/java-client/index-all.html#_S_ A B C D E F  ...

  8. Selenium+java - PageFactory设计模式

    前言 上一小节我们已经学习了Page Object设计模式,优势很明显,能更好的体现java的面向对象思想和封装特性.但同时也存在一些不足之处,那就是随着这种模式使用,随着元素定位获取,元素定位与页面 ...

  9. 【搬运】 Page Object 官方文档 (新增了Widget特性)

    Appium Java client has facilities which components to [Page Object](https://github.com/SeleniumHQ/se ...

随机推荐

  1. AC日记——【模板】最小费用最大流 P3381

    题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表 ...

  2. [Web Tools] 实用的Web开发工具

    模拟http请求:Postman https://www.getpostman.com 生成Json数据 http://www.json-generator.com/

  3. Codeforces 629 A. Far Relative’s Birthday Cake

      A. Far Relative’s Birthday Cake   time limit per test 1 second memory limit per test 256 megabytes ...

  4. R语言实战读书笔记(十三)广义线性模型

    # 婚外情数据集 data(Affairs, package = "AER") summary(Affairs) table(Affairs$affairs) # 用二值变量,是或 ...

  5. 洛谷—— P1375 小猫

    https://www.luogu.org/problemnew/show/1375 题目描述 有2n只小猫站成一圈,主人小明想把它们两两之间用绳子绑住尾巴连在一起.同时小明是个完美主义者,不容许看到 ...

  6. Android-Service基本用法、AIDL、Binder连接池详解

    本文介绍Service与Activity之间的通信,文章包含以下内容: 一.Service基本用法 二.通过AIDL实现Service与Activity跨进程通信 三.Binder连接池 四.使用Me ...

  7. js中多行字符串拼接

    前言 我们会经常遇到这样的场景,需要拼接多行字符串,在字符串中动态插入一些数据以达到业务的需求.但是js中并没有标准的多行编辑的函数,于是聪明的程序员们便脑洞大开,书写出许多有趣的方法. 1 2 3 ...

  8. Mac os x 10.8 svn server的搭建

    Mac自带了svn服务端和客户端,所以我们不用再去下载了. 1 但首先 sudo vi /etc/paths   将xcode里的Contents/developer/usr/bin加入到path   ...

  9. 如果当前地图文档中有独立的Table,通过Engine如何获取该Table?

    将IMap转为ITableCollection,通过ITableCollection.get_Table(int index);来获取该Table

  10. Direct2D教程(九)渲染位图

    概述 这篇的标题更确切的说应该叫位图画刷,这样才好和前几篇对应起来.在Direct2D中,位图的渲染也是通过画刷来实现的. Direct2D中并没有直接操作位图的接口,而是借助WIC(Windows ...