我正在对我编写的一些代码进行测试 提炼成下面粘贴的示例项目。 我遇到的问题是测试挂起测试运行器并且 我的测试用例中没有任何测试运行。
我已经将问题追踪到对 invalidate() 的调用 getChildStaticTransformation(View child, Transformation t) 我是 覆盖做一些缩放效果。
如果我注释掉对 invalidate() 的调用,那么测试就会运行。这 我调用 invalidate() 的原因是为了确保 View 得到 应用缩放效果后重新绘制。
如果我不调用 invalidate() 则 View 看起来不正确,直到 用户操作强制重新绘制屏幕。
两个问题:
- 为什么 invalidate() 会阻止测试运行?
- 我是否应该以不同的方式缩放我的 View ,而不是 需要调用 invalidate() 吗?
以下是 Eclipse Android 控制台的输出,显示位置 测试挂起:
[2011-08-19 13:51:27 - HelloGalleryTest]
------------------------------
[2011-08-19 13:51:27 - HelloGalleryTest] Android Launch!
[2011-08-19 13:51:27 - HelloGalleryTest] adb is running normally.
[2011-08-19 13:51:27 - HelloGalleryTest] Performing
android.test.InstrumentationTestRunner JUnit launch
[2011-08-19 13:51:27 - HelloGalleryTest] Automatic Target Mode: using
device '428024642BF9457'
[2011-08-19 13:51:27 - HelloGalleryTest] Uploading
HelloGalleryTest.apk onto device '428024642BF9457'
[2011-08-19 13:51:27 - HelloGalleryTest] Installing
HelloGalleryTest.apk...
[2011-08-19 13:51:29 - HelloGalleryTest] Success!
[2011-08-19 13:51:29 - HelloGalleryTest] Project dependency found,
installing: HelloGallery
[2011-08-19 13:51:29 - HelloGallery] Uploading HelloGallery.apk onto
device '428024642BF9457'
[2011-08-19 13:51:29 - HelloGallery] Installing HelloGallery.apk...
[2011-08-19 13:51:31 - HelloGallery] Success!
[2011-08-19 13:51:31 - HelloGalleryTest] Launching instrumentation
android.test.InstrumentationTestRunner on device 428024642BF9457
[2011-08-19 13:51:31 - HelloGalleryTest] Collecting test information
[2011-08-19 13:51:32 - HelloGalleryTest] Sending test information to
Eclipse
[2011-08-19 13:51:32 - HelloGalleryTest] Running tests...
下面是我写的示例项目代码和测试用例 展示了我上面描述的问题。 HelloGallery.getChildStaticTransformation(查看 child ,转换 t) 是调用 invalidate() 的方法。
下面包含的其他文件是为了完整起见,以备不时之需 尝试构建项目并观察我所描述的行为。
START::HELLO_GALLERY_PROJECT-FILES
HelloGallery.java
package com.hello;
import android.content.Context;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Transformation;
import android.widget.Gallery;
public class HelloGallery extends Gallery {
private Camera mCamera = new Camera();
/**
* The position (index) of the centered view in the gallery.
*/
public int mCenterViewPositionIndex;
public HelloGallery(Context context, AttributeSet attrs) {
super(context, attrs);
this.setStaticTransformationsEnabled(true);
}
/**
* {@inheritDoc}
*
* @see #setStaticTransformationsEnabled(boolean)
*/
protected boolean getChildStaticTransformation(View child,
Transformation t) {
t.clear();
mCamera.save();
final Matrix imageMatrix = t.getMatrix();
int position = getPositionForView(child);
t.setTransformationType(Transformation.TYPE_MATRIX);
if (child == getSelectedView()) {
mCenterViewPositionIndex = position;
t.setAlpha(1f);
mCamera.translate(-20, 20, -200);
}
else if(((mCenterViewPositionIndex - 1) == position )) {
t.setAlpha(0.5f);
// no need to zoom this view.
}
else if((mCenterViewPositionIndex + 1) == position ) {
t.setAlpha(0.5f);
// no need to zoom this view.
}
else if(((mCenterViewPositionIndex - 2) == position )) {
t.setAlpha(0.35f);
mCamera.translate(0, 0, 250);
}
else if((mCenterViewPositionIndex + 2) == position ) {
t.setAlpha(0.35f);
mCamera.translate(0, 0, 250);
}
else if(((mCenterViewPositionIndex - 3) == position )) {
t.setAlpha(0.1f);
mCamera.translate(0, 0, 350);
}
else if((mCenterViewPositionIndex + 3) == position ) {
t.setAlpha(0.2f);
mCamera.translate(0, 0, 350);
}else {
t.setAlpha(0.1f);
mCamera.translate(0, 0, 450);
}
mCamera.getMatrix(imageMatrix);
mCamera.restore();
// invalidate(); // <---- commenting out this line allows the Test
to run. Uncommenting this line will not allow the Test to run.
return true;
}
}
HelloGalleryActivity.java
package com.hello;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Gallery;
public class HelloGalleryActivity extends Activity implements OnItemClickListener {
private Gallery mGallery;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mGallery=(Gallery)findViewById(R.id.gallery);
//String array holding the values
String [] text=new String[]{"Hello","Hi","Alloha","Bonjour","Hallo","¡Hola"};
//Circular Array adapter to display our values in the gallery control
HomeGalleryAdapter adapter = new HomeGalleryAdapter(this, R.layout.gallery_item_layout, text);
mGallery.setAdapter(adapter);
mGallery.setSelection(adapter.MIDDLE);
mGallery.setOnItemClickListener(this);
mGallery.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View arg0, MotionEvent arg1) {
Log.d("HelloGalleryActivity", " --> onTouch");
return false;
}
});
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Log.d("HelloGalleryActivity", " --> onItemClick");
}
}
HelloGalleryAdapter.java
package com.hello;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class HomeGalleryAdapter extends ArrayAdapter<String> {
private LayoutInflater mLayoutInflater;
private TextView mText;
private int mLayoutId;
public static final int HALF_MAX_VALUE = Integer.MAX_VALUE/2;
public final int MIDDLE;
private String[] mObjects;
public HomeGalleryAdapter(Context context, int layoutId, String[]
lables) {
super(context, 0, lables);
mLayoutInflater = ((Activity) context).getLayoutInflater();
mLayoutId = layoutId;
mObjects = lables;
MIDDLE = HALF_MAX_VALUE - HALF_MAX_VALUE % lables.length;
}
public int getCount() {
return Integer.MAX_VALUE;
}
public String getItem(int position) {
return mObjects[position % mObjects.length];
}
public long getItemId(int position) {
return position % mObjects.length;
}
public View getView(int position, View convertView, ViewGroup group)
{
if (convertView == null) {
convertView = mLayoutInflater.inflate(mLayoutId, group, false);
}
mText = (TextView) convertView.findViewById(R.id.gallery_item_text);
mText.setText((String) getItem(position));
mText.setTextColor(Color.WHITE);
convertView.setTag(mText.getText());
return convertView;
}
}
res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/textview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<com.hello.HelloGallery
android:id="@+id/gallery"
android:layout_gravity="center"
android:spacing="0dp"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
res/layout/gallery_item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/home_gallery_item_layout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<RelativeLayout
android:id="@+id/gallery_item_background"
android:layout_width="100dip"
android:layout_height="100dip"
android:orientation="horizontal"
android:background="@drawable/gallery_item_selector">
<ImageView
android:src="@drawable/icon"
android:id="@+id/gallery_item_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
<TextView
android:id="@+id/gallery_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="20sp" />
</LinearLayout>
res/drawable/gallery_item_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/background_selected" /> <!--
pressed -->
<item android:drawable="@drawable/background_normal" /> <!--
default -->
</selector>
res/drawable/background_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#80000000"
android:endColor="#80FFFFFF"
android:angle="45"/>
<padding android:left="7dp"
android:top="7dp"
android:right="7dp"
android:bottom="7dp" />
<corners android:radius="8dp" />
</shape>
res/drawable/background_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#80000000"
android:endColor="#807EB6FF"
android:angle="45"/>
<padding android:left="7dp"
android:top="7dp"
android:right="7dp"
android:bottom="7dp" />
<corners android:radius="8dp" />
</shape>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hello"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="7" />
<application
android:icon="@drawable/icon"
android:label="@string/app_name">
<activity
android:name=".HelloGalleryActivity"
android:label="@string/app_name">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
END::HELLO_GALLERY_PROJECT-FILES
.
START::HELLO_GALLERY_TEST_PROJECT-FILES
HelloGalleryActivityTest.java(<----这个文件进入测试项目!!)
package com.hello.test;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.Gallery;
import android.widget.SpinnerAdapter;
import com.hello.HelloGalleryActivity;
public class HelloGalleryActivityTest extends
ActivityInstrumentationTestCase2<HelloGalleryActivity> {
private HelloGalleryActivity mActivity; // the activity under test
private Gallery mGallery;
private String[] mGalleryDataTestArray;
private SpinnerAdapter mGalleryData;
public HelloGalleryActivityTest() {
super("com.hello", HelloGalleryActivity.class);
mGalleryDataTestArray = new String[] { "Hello", "Hi", "Alloha",
"Bonjour", "Hallo", "¡Hola" };
}
@Override
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
mActivity = this.getActivity();
mGallery = (Gallery) mActivity.findViewById(com.hello.R.id.gallery);
mGalleryData = (SpinnerAdapter) mGallery.getAdapter();
}
public void testPreconditions() {
assertNotNull(mActivity);
assertNotNull(mGallery);
assertNotNull(mGallery.getOnItemClickListener());
assertNotNull(mGalleryData);
}
public void testInitialGalleryPosition() {
int position = mGallery.getSelectedItemPosition();
String galleryItemLabel = (String)
mGallery.getItemAtPosition(position);
assertEquals(mGalleryDataTestArray[0], galleryItemLabel);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hello.test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="12" />
<instrumentation android:targetPackage="com.hello"
android:name="android.test.InstrumentationTestRunner" />
<application android:icon="@drawable/icon" android:label="@string/
app_name">
<uses-library android:name="android.test.runner" />
</application>
</manifest>
END::HELLO_GALLERY_TEST_PROJECT-FILE
最佳答案
尝试使用 postInvalidate() 而不是 invalidate()。
我不是 100% 确定发生了什么,但我怀疑您的代码中有某些东西阻塞了 UI 线程。使用 postInvalidate() 将立即返回并让您的代码完成,这将解锁 UI 线程。
关于java - ActivityInstrumentationTestCase2 问题 - 由于我正在为其编写测试的代码中的 invalidate() 调用导致测试挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7168527/