c# 通过异步委托的执行结果更新UI界面

c# 通过异步委托的执行结果更新UI界面,第1张

已经加注释了,你看一下吧:

lblStatusText = "执行中,请稍候……";

Func<int> longTask = new Func<int>(delegate()

{

    //  模拟长时间任务

    ThreadSleep(2000);

    //  返回任务结果:5

    return 5;

});

//  发起一次异步调用,实际上就是在net线程池中执行longTask

//  这时由于是其它线程在工作,UI线程未被阻塞,所以窗体不会假死

longTaskBeginInvoke(ar =>

{

    //  使用EndInvoke获取到任务结果(5)

    int result = longTaskEndInvoke(ar);

    //  使用ControlInvoke方法将5显示到一个label上,如果没有Invoke,

    //  直接写lblStatusText="5",将会抛出跨线程访问UI控件的异常

    Invoke(new Action(() => lblStatusText = "执行结果是:" + result));

}, null);

Google在sdk40以后提供了一个自动化解决方案uiautomator:

优点:可以跨应用了;这可是亲生的;

缺点:必须sdk40以上版本;要想实现的好,最好有开发配合;java项目编译为jar后需要push到手机才能运行,也就是说必须打印日志暴力调试。

Appium基于Android InstrumentationFramework和UIAutomator,也就是说这个工具是可以跨应用的。说远了,好吧,为了帮大家更容易理解appium的使用,我这里就讲一下uiautomator的使用方法。

你应该有android-sdk吧,升级到40以上,进入目录android-sdk\tools,你会看到两个文件:

traceviewbat 和 uiautomatorviewerbat,这俩文件让你想起了monkeyrunner了吧,是的,traceviewbat就对应于hierarchyviewerbat,用来查看程序的ui界面的,通常也是使用管理员权限启动的。

好了,现在用eclipse创建一个java project,是的,你没看错,是java project不是android project,添加引用:

在projectproperties中内容为:

# Project target

target= android-16

这里的android-16需要和之前的androidjar和uiautomatorjar位置相一致。

然后呢?写代码吧,建立一个类,得,发个给大家参考:

package comuiaexamplemy;

import orgapache>

import androidgraphicsBitmap ;

import androidgraphicsBitmapFactory ;

import androidgraphicsRect ;

import androidosEnvironment;

import comandroiduiautomatorcoreUiObject;

import comandroiduiautomatorcoreUiObjectNotFoundException;

import comandroiduiautomatorcoreUiScrollable;

import comandroiduiautomatorcore UiSelector ;

import comandroiduiautomatortestrunnerUiAutomatorTestCase;

import javaioFile;

import javaioFileOutputStream;

import javaioIOException;

public class TAppWorkAssistV1  extends UiAutomatorTestCase {

public String sLog ;

public File fout = null ;

public FileOutputStream outStream = null ;

public void write2file(String filename,String sData)

{

String sLog= "" ;

// 初始化日志文件

if (Environment getExternalStorageState ()equals(EnvironmentMEDIA_MOUNTED )){

   sLog = Environment getExternalStorageDirectory()getAbsolutePath();

   try {

     fout = new File(sLog,filename);

     outStream = new FileOutputStream( fout , true );   // 此处的 true 是append

     sData=sData + "\n" ;

         outStream write(sDatagetBytes());

         outStream flush();

     outStream close();

     fout = null ;

}

catch (Exception e){

     eprintStackTrace();

}

} else {

   System out println( " 该手机没有 SD 卡 " );

}

}

public void testDemo() throws UiObjectNotFoundException {

   //1 启动 app

   getUiDevice()pressHome();

   UiObject allAppsButton = new UiObject( newUiSelector()description( "Apps" ));

   allAppsButtonclickAndWaitForNewWindow();

   UiObject appsTab = new UiObject( new UiSelector()text( "Apps" ));

   appsTabclick();

   UiScrollable appViews = new UiScrollable( newUiSelector()scrollable( true ));

   UiObject settingsApp = appViewsgetChildByText( newUiSelector()className(androidwidgetTextView class getName()), "Efilm" );

   settingsAppclickAndWaitForNewWindow();

   //2 进入主界面

   System out println( "into main view" );

   System out println(getUiDevice()waitForWindowUpdate("comeshoreefilm" , 60000));

   System out println( "intoed main view" );

   UiObject tv1 = new UiObject( new UiSelector()text( " 影院 " ));

   tv1click();

   //3 点击影院

   UiObject oyy= new UiObject( new UiSelector()description("cinema_row" ));

   System out println( "wait yingyuan come out" );

   oyywaitForExists(60000);

   System out println( "yingyuan come out" );

   oyyclickAndWaitForNewWindow();

   System out println( "click yingyuan" );

   //4 场次

   UiObject occ= new UiObject( new UiSelector()description("LinearLayout10" ));

   System out println( "wait changci come out" );

   oyywaitForExists(60000);

   System out println( "changci come out" );

   occclickAndWaitForNewWindow();

   System out println( "click changci" );

   //5 座位

   UiObject oseat= new UiObject( new UiSelector()description("cinema_shows_list_item" )index(0)childSelector( newUiSelector()description( "LinearLayout10" )));

   System out println( "wait seat come out" );

   oseatwaitForExists(5000);

   int h=getUiDevice()getDisplayHeight();

   int w=getUiDevice()getDisplayWidth();

   System out println( "(h/2,w/2)=" +h/2+ "," +w/2);

   getUiDevice()click(h/2,w/2);

   //Systemoutprintln("seat count:"+StringvalueOf(oseatgetChildCount()));

   //Systemoutprintln("seat getText:"+ oseatgetText());

   // 截座位图

   Process process;

   try {

   process = Runtime getRuntime ()exec( "screencap /mnt/sdcard/EfilmFailSnapShot01png" );

   try {

   processwaitFor();

   } catch (InterruptedException e) {                   // TODO Auto-generated catch block

   eprintStackTrace();

   }

   } catch (IOException e) {

   // TODO Auto-generated catch block

   eprintStackTrace();

   }

   //takeScreenShots("EfilmSeatSnapShot");

}

}

这个例子是随便写的,可能不够严谨。大体就这么个情况吧。下一步就是编译执行了,先插上手机usb接口,然后打开cmd,执行:

找到SDKID,也就是android create中的-t参数:

cd C:\ PROGRAM\android-sdk\tools

android list

找到t参数的值以后:

cd C:\ PROGRAM\android-sdk\tools

android create uitest-project -n TAppWorkAssistV1 -t 25 -p C:\android自动化\Tv20\TestSetting

cd C:\android自动化\Tv20\TestSetting

ant build

cd C:\android自动化\Tv20\TestSetting\bin

adb push TAppWorkAssistV1jar /data/local/tmp/

adb shell uiautomator runtest TAppWorkAssistV1jar -c comuiaexamplemy TAppWorkAssistV1

看了看,好像没有什么特别值得解释的

-n TAppWorkAssistV1:类名

-p: 项目所在目录

Ant build 把这个类编译成一个jar包:TAppWorkAssistV1jar

然后把jar包push到手机上,调用执行这个类就可以了

大致是这么个步骤,不过有一个非常重要的细节,就是如果你需要更省心,就最好把界面元素,无论动态的还是布局文件中的,都加上content-description属性,并保证唯一性,根据:

UiSelector:description(String desc)

Set the search criteria to match thecontent-description property for a widget

那就可以统一只使用这一个引用界面元素的方法就行了,就不用去想方设法利用其它的属性来引用了。

先来看下未使用 PO(PageObject) 设计模式下的代码,以网页版百度登录为例来说明。

非 PO(PageObject) 模式下的代码如下,所有内容全部写在一个方法里。

存在的问题:

PO(PageObject) 模式优化后的代码

1、WebUI 自动化需要的 driver 基础 *** 作

2、登录页面元素获取

3、登录逻辑业务的封装

4、登录测试用例将使用以上3个页面对象

可以发现,使用 PO(PageObject) 模式优化后的代码,有以下明显优势:

1)、将以下3个模块进行了单独封装 降低了模块之间的耦合度,使层次更加清晰合理,便于后期维护与复用:

2)、如果前端页面有 定位元素的 type 或 value 发生变化时,只需要修改 elementspy 文件中元素信息即可 ,不需要在测试业务模块中进行修改。

以上就是关于c# 通过异步委托的执行结果更新UI界面全部的内容,包括:c# 通过异步委托的执行结果更新UI界面、用android uiautomator做自动化测试,怎么连接真机进行、WebUI 自动化测试的经典设计模式:PO等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9783735.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-01
下一篇2023-05-01

发表评论

登录后才能评论

评论列表(0条)

    保存