新换了博客的UI,HTML5扁平化三栏样式。这几天有些忙,还有许许多多要优化的地方没时间修改,后面有时间再进行优化,博客暂且就这样子了~
天晴,心情不多云。
Edit By 小树
用文字留住时间、用博客记录生命
新换了博客的UI,HTML5扁平化三栏样式。这几天有些忙,还有许许多多要优化的地方没时间修改,后面有时间再进行优化,博客暂且就这样子了~
天晴,心情不多云。
Edit By 小树
AndroidAnnotations是一个能够让你快速进行Android开发的开源框架,它能让你专注于真正重要的地方。使代码更加精简,使项目更加容易维护,它的目标就是“Fast Android Development.Easy maintainance”.
希望此篇能帮到大家,本系列教程目录:转载请链接并注明:转自 小树技术博客 .
AndroidAnnotations注解框架之介绍+配置(一): (飞机票)
[重要]关于Android Application的介绍和用法: (飞机票)
1.使用 @EApplication 定义Application
@EApplication
public class MyApplication extends Application {
}
2.使用Application
使用 @App 把Application注射到activity或其他组件中
@EActivity
public class MyActivity extends Activity {
@App
MyApplication application;
}
@EBean
public class MyBean {
@App
MyApplication application;
}
此后,用法则与普通的android application用法一致,请参考
Android真正的入口:Application的用法介绍:链接
AndroidAnnotations是一个能够让你快速进行Android开发的开源框架,它能让你专注于真正重要的地方。使代码更加精简,使项目更加容易维护,它的目标就是“Fast Android Development.Easy maintainance”.
希望此篇能帮到大家,本系列教程目录:转载请链接并注明:转自 小树技术博客 .
AndroidAnnotations注解框架之介绍+配置(一) (飞机票)
[重要]关于Android Activity的介绍和用法:(飞机票)
@EActivity注释的Activity,其参数值必须是一个有效的布局资源id,将作为活动视图Content View的内容。
当然,你也可以不使用参数,让value为空,那么你就需要自己在onCreate()中进行视图的初始化
@EActivity(R.layout.main)
public class MyActivity extends Activity {
}
@EActivity
public class MyListActivity extends ListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
使用 @Activity 注解的 Activity ,与Fragment相同,都会由 AndroidAnnotations框架自动生成一个中间类,Activity_ ,这个类才是真正android系统识别
到和调用到的有内容的类,因此,任何跳转或者是注射,都应该使用这个类,例如:
@EActivity
public class MyActivity extends Activity {
// …
}
public final class MyActivity_ extends MyActivity {
// …
}
因此,AndroidManifest.xml中,你必须在所有使用@注解的Activity上,添加下划线_,如:
<activity android:name=”.MyListActivity_” />
A:
通常在安卓,你使用以下代码启动一个activity:
startActivity(this, MyListActivity.class);
startActivity(this, MyListActivity_.class);
// Starting the activity
MyListActivity_.intent(context).start();
// Building an intent from the activity
Intent intent = MyListActivity_.intent(context).get();
// You can provide flags
MyListActivity_.intent(context).flags(FLAG_ACTIVITY_CLEAR_TOP).start();
// You can even provide extras defined with @Extra in the activity
MyListActivity_.intent(context).myDateExtra(someDate).start();
你可以使用 startActivityForResult() 获取 activity 的返回值
MyListActivity_.intent(context).startForResult();
onCreate()
你必须实现这个方法。系统调用它当创建你的activity的时候。在你的实现中,你应该初始化你的activity的基本的组件。更重要的是,这里就是你必须调用setContentView()来定义activity用户接口而已的地方。onPause()
系统调用这个方法当用户离开你的activity(虽然不总是意味着activity被摧毁)。这通常是你应该提交任何变化,那此将会超越user session而存在的(因为用户可能不再回来)。 有若干其它生命周期回调函数你应该使用为了提供一个流畅的用户体验,并表操作异常中断会引起你的activity被中断甚至被摧毁。AndroidAnnotations是一个能够让你快速进行Android开发的开源框架,它能让你专注于真正重要的地方。使代码更加精简,使项目更加容易维护,它的目标就是“Fast Android Development.Easy maintainance”.
希望此篇能帮到大家,本系列教程目录:转载请链接并注明:转自 小树技术博客 .
AndroidAnnotations注解框架之介绍+配置(一) (飞机票)
Anno 提供了一种类型安全的方式,让你可以去调用Android SharedPreferences , 下面带来一些Preferences常用的操作,并在最后附上一个项目的Demo片段
首先,你应该创建一个以@SharedPref定义的接口,作为一个 SharedPreferences
@SharedPref
public interface MyPrefs {
// The field name will have default value "John"
@DefaultString("John")
String name();
// The field age will have default value 42
@DefaultInt(42)
int age();
// The field lastUpdated will have default value 0
long lastUpdated();
}
基于这个操作, AndroidAnnotations框架将会自动构建一个SharedPreferences子类,在你的原类名基础上加上下划线,如MyPref,你可以通过@Pref注释得到这个实例
注意: 实例的类型必须以新生成的类为类型
@EActivity
public class MyActivity extends Activity {
@Pref
MyPrefs_ myPrefs;
// ...
}
其中,定义值目前有:
@DefaultBoolean
@DefaultFloat
@DefaultInt
@DefaultLong
@DefaultString
@DefaultStringSet
@DefaultRes
// Simple edit
myPrefs.name().put(“John”);
// Batch edit
myPrefs.edit()
.name()
.put(“John”)
.age()
.put(42)
.apply();
// Preference clearing:
myPrefs.clear();
// Check if a value exists:
boolean nameExists = myPrefs.name().exists();
// Reading a value
long lastUpdated = myPrefs.lastUpdated().get();
// Reading a value and providing a fallback default value
long now = System.currentTimeMillis();
long lastUpdated = myPrefs.lastUpdated().getOr(now);
注意: anno 3.0 版本之后才有这个功能
@SharedPref
public interface MyPrefs {
@DefaultInt(0)
int versionCode();
@DefaultString("无")
String widgetBackground();
@DefaultBoolean(false)
boolean classTableAsFirstScreen();}</pre>
注意:anno 3.1 后才有此功能
@SharedPref
public interface MyPrefs {
@DefaultString(value = “John”, keyRes = R.string.myPrefKey)
String name();
@DefaultRes
String defaultPrefAge(keyRes = R.string.myOtherPrefKey);
}
你还可以通过设置value来设定pref的作用域
例如:
ACTIVITY :
名为:MyActivity_MyPrefs 的pref
ACTIVITY_DEFAULT
: 名为MyActivity 的 pref
( 可以通过activity.getPreferences() 获取到
);
APPLICATION_DEFAULT <span style="font-family: Courier New;">:</span>
使用默认的单例名称
因此,如果一个SharedPreference接口的定义是给一个应用程序application下所有activity所使用的话,应该使用以下作用域:
@SharedPref(value=SharedPref.Scope.UNIQUE)
public interface MyPrefs {
…
同样地,使用 Android PreferenceActivity
也能够改写任何已用@SharedPref注解的SharedPref
@SharedPref()
public interface MyPrefs {
…
}
public class PrefsActivity extends PreferenceActivity {
public static String PREF_NAME = "MyPrefs";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Using your MyPrefs values
this.getPreferenceManager().setSharedPreferencesName(PREF_NAME);
// Opening the layout
addPreferencesFromResource(R.xml.prefs);
}
}
SharedPref
**
@email admin@qiushurong.cn
*/
@SharedPref( value = SharedPref.Scope.UNIQUE)
public interface AppConfig {
@DefaultInt(0)
int versionCode(); // 当前的versionCode
@DefaultString(“”)
String userName(); // 用户
@DefaultString(“”)
String password(); // 密码
}
片段1
config = new cn.scau.scautreasure.AppConfig_(context);
RingerMode duringMode = RingerMode.getModeByValue(config.duringClassRingerMode().get());
RingerMode afterMode = RingerMode.getModeByValue(config.afterClassRingerMode().get());
片段2
@Pref cn.scau.scautreasure.AppConfig_ config;
/**
切换到加载所有课程模式;
*/
@OptionsItem
void menu_load_classtable_all(){
config.classTableShowMode().put(MODE_ALL);
showClassTable();
}
/**
Edit by 小树
作为一门开发语言,反射类机制是必不可少的!android也有类似的开源IOC框架,通过依赖注入(IOC)的实现思想,可以把约定好的一大串代码通过注解@的方式,以IOC技术来生成中间件,AndroidAnnotations在这方面出色,不仅体积小,而且功能强大,极大的减少了代码量,下面将带来一系列的教程。
希望此篇能帮到大家,本系列教程目录:转载请链接并注明:转自 小树技术博客 .
AndroidAnnotations注解框架之介绍+配置(一):飞机直达
AndroidAnnotations注解框架之@Pref(二): 飞机直达
AndroidAnnotations注解框架之@Activity(三):飞机直达
AndroidAnnotations注解框架之@Application(四): 飞机直达
AndroidAnnotations官网:AndroidAnnotations首页
开源于github的项目地址:AndroidAnnotations Github
AndroidAnnotations是一个能够让你快速进行Android开发的开源框架,它能让你专注于真正重要的地方。使代码更加精简,使项目更加容易维护,它的目标就是“Fast Android Development.Easy maintainance”.通过一段时间的使用发现,相比原生的Android开发,确实能够让你少些很多代码,它的首页也给出了一个简单的例子,通过例子也可以看到代码比之前几乎少写了一半。由于是开源,所以大家都可以直接拿来使用。
至于使用这个开源框架有什么好处(只有不到50k大小),我这里就不详细翻译github上的介绍了,就简单说一下特性:
1、使用依赖注入(Dependency Injection)#本博接来下几篇的文章将要介绍的开源组件都使用DI, 不熟悉的可以了解一下Inversion of Control(IoC)
2、简化的线程模型(Simplified threading model)
3、事件绑定(Event binding)
4、REST Client
5、No Magic [不知道为什么这样称呼,直译过来就是:无魔法,它的意思是:AndroidAnnotations在编译的时候会产生一个子类(接下来你会明白),你查看这个子类,可以看到它是如何工作的]
更多的介绍可以前往官网或者Github上的项目去查看,它带有超级详细和全面的wiki,CookBook和API文档,十分爽心悦目。
开发工具:Eclipse & android stdio & other (本篇以eclipse为例子,其他IDE请参考官网)
JDK版本:jdk1.6 以上
构建工具:Ant(Eclipse默认的build tool,因此无需装额外的插件)
androidannotations:3.1 (请前往 发行地址 下载)
1,准备好需要的环境,见上文
2,配置好项目文件
3,配置Ant
4,配置Eclipse
首先需要有一个普通的android项目,下载并解压Anno 3.1的JAR包,解压后有两个jar包,androidannotations-api-2.7.1.jar放置于项目libs文件夹,androidannotations-2.7.1.jar放置于项目compile-libs文件夹下
(compile-libs需要自己创建,创建在项目的根目录下)
(在项目根目录下,创建 build.xml和custom_rules.xml)
<?xml version=”1.0” encoding=”UTF-8”?>
<project name=”这里是项目名” default=”help”>
<property file="local.properties" />
<property file="ant.properties" />
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<loadproperties srcFile="project.properties" />
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<import file="custom_rules.xml" optional="true" />
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>
<?xml version=”1.0” encoding=”UTF-8”?>
<property
name=”generated.dir”
value=”.apt_generated” />
<property
name=”generated.absolute.dir”
location=”${generated.dir}” />
<property
name=”java.compilerargs”
value=”-s '${generated.absolute.dir}'” />
<target name=”-pre-compile” >
<mkdir dir="${generated.absolute.dir}" />
</target><target
name=”-compile”
depends=”-pre-build, -build-setup, -code-gen, -pre-compile” >
<do-only-if-manifest-hasCode elseText="hasCode = false. Skipping..." >
<!-- merge the project's own classpath and the tested project's classpath -->
<path id="project.javac.classpath" >
<path refid="project.all.jars.path" />
<path refid="tested.project.classpath" />
<path path="${java.compiler.classpath}" />
<fileset
dir="compile-libs"
includes="*.jar" />
</path>
<javac
bootclasspathref="project.target.class.path"
classpathref="project.javac.classpath"
debug="true"
destdir="${out.classes.absolute.dir}"
encoding="${java.encoding}"
extdirs=""
fork="${need.javac.fork}"
includeantruntime="false"
source="${java.source}"
target="${java.target}"
verbose="${verbose}" >
<src path="${source.absolute.dir}" />
<src path="${gen.absolute.dir}" />
<compilerarg line="${java.compilerargs}" />
</javac>
<!-- if the project is instrumented, intrument the classes -->
<if condition="${build.is.instrumented}" >
<then>
<echo level="info" >
Instrumenting classes from ${out.absolute.dir}/classes…
</echo>
<!-- build the filter to remove R, Manifest, BuildConfig -->
<getemmafilter
appPackage="${project.app.package}"
filterOut="emma.default.filter"
libraryPackagesRefId="project.library.packages" />
<!--
define where the .em file is going. This may have been
setup already if this is a library
-->
<property
name="emma.coverage.absolute.file"
location="${out.absolute.dir}/coverage.em" />
<!-- It only instruments class files, not any external libs -->
<emma enabled="true" >
<instr
instrpath="${out.absolute.dir}/classes"
metadatafile="${emma.coverage.absolute.file}"
mode="overwrite"
outdir="${out.absolute.dir}/classes"
verbosity="${verbosity}" >
<filter excludes="${emma.default.filter}" />
<filter value="${emma.filter}" />
</instr>
</emma>
</then>
</if>
<!-- if the project is a library then we generate a jar file -->
<if condition="${project.is.library}" >
<then>
<echo level="info" >
Creating library output jar file…
</echo>
<property
name="out.library.jar.file"
location="${out.absolute.dir}/classes.jar" />
<if>
<condition>
<length
length="0"
string="${android.package.excludes}"
trim="true"
when="greater" />
</condition>
<then>
<echo level="info" >
Custom jar packaging exclusion: ${android.package.excludes}
</echo>
</then>
</if>
<propertybyreplace
name="project.app.package.path"
input="${project.app.package}"
replace="."
with="/" />
<jar destfile="${out.library.jar.file}" >
<fileset
dir="${out.classes.absolute.dir}"
excludes="${project.app.package.path}/R.class ${project.app.package.path}/R$*.class ${project.app.package.path}/BuildConfig.class"
includes="**/*.class" />
<fileset
dir="${source.absolute.dir}"
excludes="**/*.java ${android.package.excludes}" />
</jar>
</then>
</if>
</do-only-if-manifest-hasCode>
</target>
在eclipse中,右键项目,选择属性Properties
Properties>> Java Compiler ,勾上Enable,确保编译器版本为1.6以上
Properties >> Java Compiler >> Annotation Processing >> 勾选Enable annotation processing(开启)
Properties >> Java Compiler >> Annotation Processing >> Factory Path >> 添加jar包,选择该项目,打开compile-libs目录下的androidannotations-2.7.1.jar
选择eclipse菜单,Project>>clean>>选上该项目>>确定clean
这里附上一个简单的Demo,可以导入后,继续Ant和eclipse的配置即可正常使用,如有问题,请留言。
注:文章部分内容转载自renqingping(博客园)
Android使用GoogleDalvik VM,相对于传统Java VM而言有着很大的不同,在Sun的Java体系中入口点和标准c语言一样是main(),而每个Android程序都包含着一个Application实例,一个Application实例中有多个Activity、Service、ContentProvider或Broadcast Receiver。因为大部分的应用都包含Activity所以,说很多网友认为是Activity的onCreate,但是你没有发现你的工程中有多个Activity吗? 你可能没有见过没有Activity的Android应用吧。
其实在android.app.Application这个包的onCreate才是真正的Android入口点,只不过大多数开发者无需重写该类,他的继承关系如下图:
java.lang.Object
android.app.Application类包含了4个公开的方法
void onConfigurationChanged(Configuration newConfig)
void onCreate() //这里才是真正的入口点。
void onLowMemory()
void onTerminate()
Application和Activity,Service一样是Android框架的一个系统组件,当Android程序启动时系统会创建一个Application对象,用来存储系统的一些信息。
Android系统自动会为每个程序运行时创建一个Application类的对象且只创建一个,所以Application可以说是单例(singleton)模式的一个类。
通常我们是不需要指定一个Application的,系统会自动帮我们创建,如果需要创建自己的Application,那也很简单!创建一个类继承Application并在AndroidManifest.xml文件中的application标签中进行注册(只需要给application标签增加name属性,并添加自己的 Application的名字即可)。
启动Application时,系统会创建一个PID,即进程ID,所有的Activity都会在此进程上运行。那么我们在Application创建的时候初始化全局变量,同一个应用的所有Activity都可以取到这些全局变量的值,换句话说,我们在某一个Activity中改变了这些全局变量的值,那么在同一个应用的其他Activity中值就会改变。
Application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以可以通过Application来进行一些,如:数据传递、数据共享和数据缓存等操作。
在Android中,可以通过继承Application类来实现应用程序级的全局变量,这种全局变量方法相对静态类更有保障,直到应用的所有Activity全部被destory掉之后才会被释放掉。
public class CustomApplication extends Application
{
private static final String VALUE = “Harvey”;
private String value;
@Override
public void onCreate()
{
super.onCreate();
setValue(VALUE); // 初始化全局变量
}
public void setValue(String value)
{
this.value = value;
}
public String getValue()
{
return value;
}
}
注:继承**Application类,主要重写里面的onCreate()方法(android.app.Application包的onCreate()才是真正的Android**程序的入口点),就是创建的时候,初始化变量的值。然后在整个应用中的各个文件中就可以对该变量进行操作了。
<application
android:name=”CustomApplication”>
</application>
实例代码:
/**
*/
public class CustomApplication extends Application
{
private static final String VALUE = “Harvey”;
private String value;
@Override
public void onCreate()
{
super.onCreate();
setValue(VALUE); // 初始化全局变量
}
public void setValue(String value)
{
this.value = value;
}
public String getValue()
{
return value;
}
}
public class FirstActivity extends Activity
{
private CustomApplication app;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
app = (CustomApplication) getApplication(); // 获得CustomApplication对象
Log.i("FirstActivity", "初始值=====" + app.getValue()); // 获取进程中的全局变量值,看是否是初始化值
app.setValue("Harvey Ren"); // 重新设置值
Log.i("FirstActivity", "修改后=====" + app.getValue()); // 再次获取进程中的全局变量值,看是否被修改
Intent intent = new Intent();
intent.setClass(this, SecondActivity.class);
startActivity(intent);
}
}
注:只需要调用**Context的 getApplicationContext或者Activity的getApplication方法来获得一个Application对象,然后再得到相应的成员变量即可。它是代表我们的应用程序的类,使用它可以获得当前应用的主题和资源文件中的内容等,这个类更灵活的一个特性就是可以被我们继承,来添加我们自己的全局属性。**
public class SecondActivity extends Activity
{
private CustomApplication app;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
app = (CustomApplication) getApplication(); // 获取应用程序
Log.i("SecondActivity", "当前值=====" + app.getValue()); // 获取全局值
}
}
<?xml version=”1.0” encoding=”utf-8”?>
<manifest
xmlns:android=”http://schemas.android.com/apk/res/android“
package=”com.android.test”
android:versionCode=”1”
android:versionName=”1.0”>
<uses-sdk
android:minSdkVersion=”8” />
<application
android:icon="@drawable/icon"
android:label="@string/app_name"
android:name="CustomApplication">
<!-- 将我们以前一直用的默认Application设置成自定义的CustomApplication -->
<activity
android:name=".FirstActivity"
android:label="@string/app_name">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:label="@string/app_name">
</activity>
</application>
</manifest>
注:
在某些情况下可能会遇到getApplication返回null的情况,有可能是调用getApplication的时机不对,如果是在类未定义完成的地方(比如变量定义部分),此时无法得到实例,所以就会出现空指针
在IBM公司的软件管理平台JTS上,从EXCEL文件导入测试用例到RQM中是十分之重要和实用的,很多客户也是要求必须要有如此的功能,本篇文档主要是一个工具的指南,因为RQM本身并不可以导入EXCEL,但是IBM公司提供了这么一个工具:RQMExcelWordImporter,that’s Amazing!本文内容大部分参考IBM官网的帮助,写得可能不好,请见谅!
本文档版本:4.0,和5.0应该差不多
实际基于质量管理平台:IBM JazzTeamServer Rational Quality Manager 5.0
修订人:小树 admin@qiushurong.cn # 2014-09-17 @guangzhou Changeman
RQM-Extras-RQMExcelWordImporter
打开网页后,点击download,选择qm,点击all download,找到RQM-Extras-RQMExcelWordImporter,需要登录,没有用户的话需要注册,登录后进行下载。
http://www.ibm.com/developerworks/cn/rational/1312_zhangjin_rqmbestpractice/
注意:
安装需要MicroSoft office 2003 sp3 以上版本,推荐2003或2007.
安装需要.net FramWork 2.0.以上支持.
由于修改了office的菜单和加载项,所以需要杀毒软件的放行.
下载 RQM-Extras-RQMExcelWordImporter-5.0.zip,解压后执行RQMExcelImporterX64setup.exe
安装完成后,启动 Excel,可以看到在 Add-Ins(加载项) 下的 RQM 项。
注意:如果你是X64系统,请使用X64的安装包,如果使用X64的安装包后发现并没有找到这个选项,请直接使用默认安装包即可。(因为有可能你的系统虽然是64位的,但是你的office软件确实X86或者说是32位的)
在 RQM 下,选择 Export to Repository,可以看到如图 10 所示窗口:
图 10. Export to RQM
输入 RQM Server, Username, Password,连接好 RQM Server 之后,选择 Project。这里需要注意的是使用 RQM Excel Importer 连接 RQM 的用户必须有 Data Migration 的角色,如图 11 所示:
图 11. RQM Excel Importer 用户所需要的角色
如图 10 中所示,导入 Test Cases 时我们需要一个配置文件(TestCases.cfg)。在这个文件中我们会配置在 Excel 中的行和列对应到 Test Cases 的各个组成部分,配置文件如清单 5 所示:
testcase.XLSStartRow=2
testcase.dc:title=B
testcase.dc:description=E
testcase.jzalm:owner=C
testcase.Section(“myns:com.ibm.rqm.planning.editor.section.testCaseDesign”,\”RQM-KEY-TC-DESIGN-TITLE”)=F
testcase.Section(“myns:com.ibm.rqm.planning.editor.section.testCasePreCondition”,\”RQM-KEY-TC-PRE-COND-TITLE”)=K
在清单 5 中,
第一行表示导入到 RQM 中的 test case 是从 Excel 文档中的第2行开始。
第二行表示 test case 的 title 对应的是 Excel 文件中的 B 列。
第三行表示 test case 的 description 对应的是 Excel 文件中的 E 列。
第四行表示 test case 的 owner 对应的是 Excel 文件中的 C 列。
第五行分别表示 test case 的 Design 对应的是Excel 文件中的 F 列。
第六行分别表示 test case 的 Precondition 对应的是Excel 文件中的和 K 列。
//业务域
testcase.category term=”业务域”.value=”01 登记”
//模块
testcase.category term=”模块”.value=”011001_设立税务登记”
//指定工作表
testcase.XLSWorksheetID=”测试用例汇总”
//从第*行开始读取
testcase.XLSStartRow=2
//测试用例-B
testcase.customAttributes identifier=”js_attr_csylbh2”.name=B1.type=”SMALL_STRING”.value=B
//测试用例-标题C
testcase.dc:title=C
//测试用例-优先级D
testcase.priority=D
//测试用例-前置条件E
testcase.Section(“myns:js_section_qztj”,”前置条件”)=RichText(E)
//测试用例-测试操作步骤及内容F
testcase.Section(“myns:js_section_csczbzjnr”,”测试操作步骤及内容”)=RichText(F)
//测试用例-关键点G
testcase.Section(“myns:js_section_gjd”,”关键点”)=RichText(G)
//测试用例-测试数据要求H
testcase.Section(“myns:js_section_cssjyq”,”测试数据要求”)=RichText(H)
//测试用例-关键点预期效果I
testcase.Section(“myns:js_section_gjdyqxg”,”关键点预期效果”)=RichText(I)
//测试用例-用例预期效果J
testcase.Section(“myns:js_section_ylyqxg”,”用例预期效果”)=RichText(J)
//测试用例-关联流程测试用例编号K
testcase.customAttributes identifier=”js_attr_gllccsylbh2”.name=K1.value=RichText(K)
//测试用例-编写人L
testcase.customAttributes identifier=”js_attr_bxr2”.name=L1.type=”SMALL_STRING”.value=L
//测试用例-审核意见M
testcase.customAttributes identifier=”js_attr_shyj2”.name=M1.type=”SMALL_STRING”.value=M
//测试用例-审核人N
testcase.customAttributes identifier=”js_attr_shr2”.name=N1.type=”SMALL_STRING”.value=N
//测试用例-备注O
testcase.Section(“myns:js_section_bz”,”备注”)=RichText(O)
//测试用例-所有者
testcase.alm:owner=”jazzadmin”
//测试用例-权重
testcase.weight=”100”
当 Export To Repoitory 执行成功后,可以在 RQM 查看导入的 Test Cases,如下:
通过上述介绍对比我们可以看到,RQM中,测试用例的导入的重心就是测试用例EXCEL的配置文件。
附上RQM-importer 的英文官方文档
附上测试用例导入的例子(国税局测试用例)
最近在项目中,需要去做一个页面的中英文切换,因此用到了struts自带的国际化 i18n 包,由于我所在的项目是 struts 1.x ,但是网上大多都是 struts 2 因此我把两个都一起记录下来了,基本的操作是一样的。
i18n(其来源是英文单词 internationalization 的首末字符i和n,18为中间的字符数)是“国际化”的简称。在资讯领域,国际化(i18n)指让产品(出版物,软件,硬件等)无需做大的改变就能够适应不同的语言和地区的需要。对程序来说,在不修改内部代码的情况下,能根据不同语言及地区显示相应的界面。 在全球化的时代,国际化尤为重要,因为产品的潜在用户可能来自世界的各个角落。
struts.custom.i18n.resources=messageResource
或在struts.xml中加入
<constant name=”struts.custom.i18n.resources” value=”messageResource”></constant>
名称语言代码国家代码. Properties
如果创建中文和英语国际化,那么资源文件名称为
messageResource_zh_CN.properties和messageResource_en_US.properties
通过使用标签<s:text name=”label.helloWorld”/>输出国际化
label.helloWorld为资源文件中定义的key
在messageResource_en_US.properties加入以下内容
label.hello=hello {0}
label.helloWorld=hello,world
在messageResource_zh_CN.properties加入以下内容
label.hello=你好 {0}
label.helloWorld=你好,世界
(1). <s:text name=”label.helloWorld”/>
<s:property value=”%{getText(‘label.helloWorld’)}”/>
上面两个都为输出一个hello word的两种表示
<s:textfield name=”name” key=”label.helloWorld”/>
<s:textfield name=”name” label=”%{getText(‘label.helloWorld’)}”/>
显示一个文本框,文本框的标题进行国际化
(2). 使用<s:i18n>标签指定从某个特定的资源文件中取数据
<s:i18n name=”messageResource”>
<s:text name=”label.helloWorld”></s:text>
</s:i18n>
指定在从messageResource取资源
(3).
<s:text name=”label.hello”>
<s:param>callan</s:param>
</s:text>
使用带参数的资源.<s:param>可以替换label.hello=hello {0}中的{0}
Action的国际化主要是通过getText(String key)方法实现的
String str1 = getText(“label.helloWorld”);
在messageResource_en_US.properties加入以下内容
userName=userName
userName.required=${getText(‘userName’)} is required
在messageResource_zh_CN.properties加入以下内容
userName=用户名
userName.required=${getText(‘userName’)} 不能为空
在Action中
String str4 = getText(“userName.required”);
System.out.println(str4);
userName.required=${getText(‘userName’)}会取国际化的用户名
<field name=”userName”>
<field-validator type=”requiredstring”>
<message key=”userName.required”> </message>
</field-validator>
</field>
由于老板的需求,是要在配置文件里面进行单一性质的修改,所以我的解决方案如下:
修改struts配置文件web.xml
添加/WEB-INF/language.xml分支
/WEB-INF/language.xml设置要读取的字库
读取
config/Language_Chinese.properties
config/Language_English.properties
JSP页面
包含struts-lib
<%@ taglib prefix=”bean” uri=”http://struts.apache.org/tags-bean”%>
使用标签
<bean:message key=”hello”/>
切换语言方法:找到 WEB_INF/language.xml 按照注释内容进行修改
在许许多多的android项目中,下拉刷新是必不可少的一个小模块,最近的一个项目中,很多模块都需要实现这么一个功能,最后采用的是Github上很火的开源项目,PullToRefresh,下面,简单说一下PullToRefresh的使用方法和个人的心得。
开源项目地址:https://github.com/johannilsson/android-pulltorefresh
到开源项目的官网下载整个项目,导入到eclipse中,到你的主项目,右键,项目属性,选择android,在最下面,把刚刚导入进来的pulltorefresh项目add成为一个lib引用。如图:点击放大
附上代码以及解释:
<!-- 带下拉刷新的ListView --> <com.handmark.pulltorefresh.library.PullToRefreshListView xmlns:ptr="http://schemas.android.com/apk/res-auto" android:id="@+id/pull_refresh_list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:cacheColorHint="#00000000" android:divider="#19000000" android:dividerHeight="4dp" android:fadingEdge="none" android:fastScrollEnabled="false" android:footerDividersEnabled="false" android:headerDividersEnabled="false" android:smoothScrollbar="true" ptr:ptrAnimationStyle="rotate" //下拉时,图标的动画,rotate是旋转 ptr:ptrHeaderBackground="#FFF8F8F8" //下拉时,滑出的下拉块背景颜色 ptr:ptrMode="both" //下拉刷新的模式,both是上拉和下拉 ptr:ptrDrawable="@drawable/loading4"> //下拉时候的图标
首先是获取实例
mPullRefreshListView = (PullToRefreshListView) parentView.findViewById(R.id.pull_refresh_list);设置音效
SoundPullEventListener<ListView> soundListener = new SoundPullEventListener<ListView>(parentActivity); soundListener.addSoundEvent(State.PULL_TO_REFRESH, R.raw.pull_event); soundListener.addSoundEvent(State.RESET, R.raw.reset_sound); soundListener.addSoundEvent(State.REFRESHING, R.raw.refreshing_sound); mPullRefreshListView.setOnPullEventListener(soundListener);设置提示文字
//设置提示信息 ILoadingLayout startLabels = mPullRefreshListView .getLoadingLayoutProxy(); startLabels.setPullLabel("向下拉刷新...");// 刚下拉时,显示的提示 startLabels.setRefreshingLabel("松开刷新...");// 刷新时 startLabels.setReleaseLabel("正在加载中...");// 下来达到一定距离时关于设置提示文字的,有一个地方要说的是, mPullRefreshListView.getLoadingLayoutProxy(参数,参数); 这一句,不传参数的话,默认是同时设置 下拉刷新 和 上拉加载更多 的文本。 添加参数:true,false 是设置 下拉刷新 的文本。 添加参数:false,true 是设置 上拉加载更多 的文本。 例如:
//设置 下拉刷新 提示信息 ILoadingLayout startLabels = mPullRefreshListView.getLoadingLayoutProxy(true,false); startLabels.setPullLabel("下拉重新刷新...");// 刚下拉时,显示的提示 startLabels.setRefreshingLabel("不要命刷新中...");// 刷新时 startLabels.setReleaseLabel("松开重新刷新...");// 下来达到一定距离时 //设置 加载更多 提示信息 ILoadingLayout endLabels = mPullRefreshListView.getLoadingLayoutProxy(false,true); endLabels.setPullLabel("上拉加载更多...");// 刚下拉时,显示的提示 endLabels.setRefreshingLabel("不要命加载中...");// 刷新时 endLabels.setReleaseLabel("松开加载更多...");// 下来达到一定距离时效果: [![pulltorefresh-3](http://www.qiushurong.cn/wp-content/uploads/2014/08/pulltorefresh-3-300x191.jpg)](http://www.qiushurong.cn/wp-content/uploads/2014/08/pulltorefresh-3.jpg) ### 1.4 添加一个监听器
// 设置刷新监听器 mPullRefreshListView.setOnRefreshListener(new OnRefreshListener<ListView>() { @Override public void onRefresh(PullToRefreshBase<ListView> refreshView) { // 设置最近刷新时间为当前时间 String label = DateUtils.formatDateTime(parentActivity.getApplicationContext(), System.currentTimeMillis(), DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL); refreshView.getLoadingLayoutProxy().setLastUpdatedLabel(label); // 在这这个GetDataTask线程里面进行刷新处理 new GetDataTask().execute(); } });这样就完成了一个下拉刷新的操作了 但是我们现在并没有添加任何UI,一般来说,都是利用这个下拉刷新listview本身进行条目UI的操作的。 ### 1.5 在PullToRefreshListView中获取我们要的listView 如下:直接获取这个PullToRefreshListView的里面嵌套的listview,来存放我们要显示的内容
ListView actualListView = mPullRefreshListView.getRefreshableView(); //这个actualListView 就是我们真正可以用来放数据的视图view // 注册视图 registerForContextMenu(actualListView); //实例化一个list,存放我们的数据 mListItems = new LinkedList<String>(); mListItems.add("初始化数据"); //实例化一个适配器,把数据和UI进行关联 mAdapter = new ArrayAdapter<String>(parentActivity, android.R.layout.simple_list_item_1, mListItems);
既然有 下拉刷新 和 上拉加载更多,但他们都是同一个被调用的方法,那么怎么区分呢?
方法:修改开源项目,添加对header和footer的判断,通过header和footer的是否显示 来判断是上拉还是下拉
首先,在我们之前导入的项目中,找到PullToRefreshAdapterViewBase这个类
添加这么2个方法
public boolean isHeaderShown() { return getHeaderLayout().isShown(); } public boolean isFooterShown() { return getFooterLayout().isShown(); }然后clean一下主项目,让他重建一下lib包,之后在主项目的监听器里面,进行判断
mPullRefreshListView.setOnRefreshListener(new OnRefreshListener<ListView>() { @Override public void onRefresh(PullToRefreshBase<ListView> refreshView) { //这2个方法是我修改了 PullToRefresh 项目后添加进去的,原本开源的项目是没有的。 //判断是 上拉 还是 下拉 if(mPullRefreshListView.isHeaderShown()){ String label = DateUtils.formatDateTime(parentActivity.getApplicationContext(), System.currentTimeMillis(),DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL); refreshView.getLoadingLayoutProxy(true,false).setLastUpdatedLabel(label); // 开始下拉刷新 }else if(mPullRefreshListView.isFooterShown()){ String label = DateUtils.formatDateTime(parentActivity.getApplicationContext(), System.currentTimeMillis(),DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL); refreshView.getLoadingLayoutProxy(false,true).setLastUpdatedLabel(label); // 开始加载更多 } } });这样子就初步实现了一个区分的功能了 ### 1.7 在list尾端添加监听器 有时候我们需要在用户滑动到list尾端的时候进行一个提示,或者进行数据的加载,那么会用到这个:
// 在list尾端添加一个监听器 mPullRefreshListView.setOnLastItemVisibleListener(new OnLastItemVisibleListener() { @Override public void onLastItemVisible() { Toast.makeText(parentActivity, "到达尾端,上拉可加载更多...", Toast.LENGTH_SHORT).show(); } });
(明天再续)