现在的位置: 首页 > 综合 > 正文

android小问题备忘

2013年10月10日 ⁄ 综合 ⁄ 共 9211字 ⁄ 字号 评论关闭

本文原创http://blog.csdn.net/yanbin1079415046,转载请注明出处。 

 最近做项目中遇到不少的问题,每每总是在解决之后才恍然大悟。相信每位朋友在实际开发中总会遇到这样或者那样的问题,但是其实有些问题总要我们稍微留意就可以避免。这篇文章用来记录在开发过程中遇到的一些小问题,或是粗心,或是技术不够引起,只为在以后的开发中多多注意。希望有兴趣的朋友也把自己的小问题贴在回复或者私信发给我,作为程序员,这些小问题都是我们宝贵财富,希望有意愿的朋友不吝分享自己的经验,以帮助更多的人。

一:小问题篇

1、动态loading框不会转动,只显示一张静态的图片。 (ps:这个问题比较傻,当初是因为电视项目,无法连上电视,因此一时半会没看到错误信息,如果可以联机调试,这个问题一debug就可以出来。但是这个知识点还是值得注意的。)

问题描述:这个问题本来可以用两张图很形象的说明,但是暂时还不会弄个动态的图尴尬,因此就把代码简单的贴一下,配合代码说一下需要实现的功能从而引出出现的问题。这个问题要实现的功能是在请求网络数据的时候,在activity上出现一个一直在转的loading框(一张静态的图片,开一个动画让其转动),当数据加载完成后loading框消失,数据显示。但是本人在实际操作的过程中,出现了如下的问题:loading框一直就是静态的图片,也就是说图片不会转。。。

功能性代码如下:

主页面xml布局文件:main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:layout_gravity="center"
    android:background="@android:color/white"
    tools:context=".TestActivity" >
	<include 
	    android:layout_marginTop="50dp"
	    android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
	    layout="@layout/loading"
	    />
	<TextView 
	    android:layout_marginTop="20dp"
	    android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:layout_gravity="center"
    	android:text="测试loading框有没有动"
    	android:textColor="@android:color/black"
    	
	    />
</LinearLayout>

include中的loading.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/use_imagedown_loading"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
>
	   <ImageView android:id="@+id/loading_pb"  
    		android:layout_height="90dp" android:layout_width="90dp"  
    	 	android:layout_centerHorizontal="true"
    	 	android:layout_centerVertical="true"
     		android:enabled="false" 
     		android:background="@drawable/loading"
     />  
</RelativeLayout>

 

测试用TestActivity.java:

import android.os.Bundle;

public class TestActivity extends BaseActivity {     /** Called when the activity is first created. */     @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.main);     } }

 

 

 BaseActivity.java:  BaseActivity很简单,就是初始化名为loading_pb的loading框,让其转动。动画文件在BaseActivity的下面。

 

import android.app.Activity; import android.os.Bundle; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.ImageView;

public class BaseActivity extends Activity{  @Override  protected void onCreate(Bundle savedInstanceState) {   initView();   super.onCreate(savedInstanceState);  }

   /**   * 初始化loading框   */  private void initView() {   if (findViewById(R.id.loading_pb) != null)   {    ImageView view = (ImageView) findViewById(R.id.loading_pb);    Animation animation = AnimationUtils.loadAnimation(this,R.anim.loading_anim);//开始一个动画文件    animation.setRepeatCount(Animation.INFINITE);//立即重复动画    view.startAnimation(animation);   }  } }

 

动画文件loading_anim.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
	 <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/linear_interpolator"  
     android:fromDegrees="0" android:toDegrees="+720" android:duration="2000"  
     android:pivotX="50%" android:pivotY="50%" android:repeatCount="infinite" />  
</set>

但是我按照上面的代码来跑程序,loading框根本不会转动。看了一下代码,貌似没什么问题。想偷懒的同学可以直接下这个源代码观察一下效果即可。

工程下载地址:

http://download.csdn.net/detail/yanbin1079415046/4548638

下面整理一下上面我们做的事。在TestActivity的mainactivity中include进去了一个 loading框,它本来只是一张静态的图片。但是由于我们在BaseActivity的initView方法中获得了子类的布局文件中的这个loading_pb,并且给它加了一个动画,所以在TestActivity中它应该是可以转动的啊。逻辑是没错的。但是我们的loading框确实没出来。前面说过是电视项目,当初没有联机调,所以出了这个问题。后来仔细看看了,打了几个toast(当初的机顶盒啊,害死人了,只有靠U盘拷来拷去的调),发现问题是这样产生的。

问题产生原因:在TestActivity中我们把setContentView放在了调用父类onCreate方法之前,也就是说,BaseActivity 的initView中那个if条件过不去。所以loading框就不会动了。这个问题的迷惑在于,loading图片出来了,但是不会动。所以。。。

问题解决方法:将setContentView(R.layout.main);放在super.onCreate(savedInstanceState);之前即可。

2、 工程可以正常编译,但是运行时报:java.lang.NoClassDefFoundError。

解决办法: 这里说的是能正常编译。如果不能正常编译的话,请检查一下相应的类是否正确导入。我们这里的情况,检查报错的信息,在jar文件中这个类是可以找到的。假设我们放在了src的libs目录底下,并且已经将其Add To Build Path了。此时我们只要将libs文件夹Use as Source Folder即可。具体操作步骤是:libs(具体与你放jar包的文件夹名字相同)-->右键-->build-->Use
as Source Folder。

3、关于OnActivityResult()方法不会调用的问题。

①:startActivityForResult中的request必须大于0。

②:跳转到的那个Activity必须有setResult方法,否则不会被调用。

③:跳转到的Activity的lanuchmode设置成了SingleTask,也就是这两个Activity不在一个任务栈中了,所以无法调用。 

曾经在一个项目中调用了360相机来拍照,结果拍完照以后,onActivityResult()根本不会被调用。后来使用如下的代码解决了这个问题,即:在start照相机程序的时候给其附带一个Extra,从而将相片输出临时存放在一个Uri中,然后从该Uri中拿出数据即可。(image可以,video也当然就可以这样做)。具体代码如下:

 

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//打开照相程序
/**
* MediaStore.EXTRA_OUTPUT文档说明:
* The name of the Intent-extra used to indicate a content resolver Uri 
* to be used to store the requested image or video.
*/
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(imgpath)));//将图片或者视频文件存在该uri下。
startActivityForResult(intent, TAKE_PICTURE);//TAKE_PICTURE为自定的常量

4、每次更新drawable下的图片文件都会增加一个文件:thumbs.db。

解决方法:该文件时缓存的缩略图文件。只需在电脑的  文件夹选项--查看中设置不缓存缩略图即可。

5、关于Bitmap.recycle()方法的作用

一个图片加载到内存里,其实是有两部分数据组成,一部分是图片的相关描述信息,另一部分就是最重要的像素信息(这部分是有byte数组组成的),android系统为了提高对图片的处理效率,对于图片的处理都是调用了底层的功能(由C语言实现的),也就是说一个图片加载到内存里后是使用两部分的内存区域,简单的说:一部分是java可用的内存区,一部分是c可用的内存区,这两个内存区域是不能相互直接使用的,
这个bitmap对象是有java分配的,当然不用的时候系统会自动回收了,可是那个对应的C可用的内存区域jvm是不能直接回收的,这个只能调用底层的功能释放。所以你要调用recycle方法来释放那一部分内存。

原文地址:http://blog.sina.com.cn/s/blog_7d35fa1a01016thb.html

6、接入人人网时,一开始用的很好,突然某一天出现如下的问题:

无效的测试用户,测试用户的好友总数必须小于或等于10

这个问题一般是在人人发布了专门的移动开发者平台之后出现的。咨询了一下人人的工程师,出现问题的原因如下:

开放平台和移动开发者平台申请app的账号串用了。据人人工程师的说法,人人网开放平台和人人移动开发者平台之间账号是独立的。因为他们提供了两套api,但是可以实现同一功能。假如你在人人移动开发者平台上申请了一个app,并且该app已经通过审核上线了。在这个app里你使用的是移动开发者平台的那个api来实现相应的功能,假如某一天你的app改版了,并且使用人人开放平台的api来实现相应的功能,但是你的app的key和secret还是用的移动开发者平台上的那个app的key和secret,此时就会出现这样的问题了。解决办法是使用一致的api或者重新申请一下app吧。

6、客户端接入开心网的一些问题

  客户端接入开心网,在开心网加载授权框的dialog还未消失的时候,点击取消,不让dialog继续加载,退出开心网授权的页面。一段时间之后,我们的应用程序莫名其妙的崩掉。检查异常日志,发现时progressDialog未关闭所致。因为在开心网的授权页面中,授权dialog里面嵌套一个ProgressDialog。而在外面的dialog执行dismiss的时候,未对ProgressDialog做相应的处理,于是出现了异常。

解决办法是在KaixinDialog.java中重写dismiss方法,代码如下:

@Override
	public void dismiss(){
		if(mProgress != null){
			mProgress.dismiss();
		}
		super.dismiss();
	}

:小技巧篇

1、自定义的RadioButton,使图片和文字是紧挨着的。

当我们自定义了RadioButton之后,如果不进行设置,RadioButton的图片和文字会自由的排列,我们只需要进行如下的设置即可让图片和文字挨在一起,设置单选框的background为null,然后图片使用button属性来设置。xml布局文件示例如下:

<RadioButton android:id="@+id/rb1" android:text="自定义单选框" android:textColor="#000000" 
android:layout_weight="1" android:layout_width="wrap_content"
android:background="@null"
android:gravity="center"
android:button="@drawable/radio_button" android:paddingLeft="23dp"
/>

2、去除ExpandableListView分组Group左边的指示图标:
ExpandableListView..setGroupIndicator(null);

3、第三方客户端(新浪微博,腾讯微博,人人网,开心网)取消授权:

第三方客户端的授权比较简单,参看各大开放平台给出的demo就可以。但如若要取消授权应该如何做。下面就给出相应的解决办法,一旦可以取消授权,登出操作自然就不难了吧。

新浪微博:在Weibo类中有一个dialog(...)方法,加一个强制登陆的参数就可以实现取消授权的效果了。

public void dialog(Context context, WeiboParameters parameters,
            final WeiboDialogListener listener) {
    	parameters.add("forcelogin", "true");//强制登陆
        parameters.add("client_id", APP_KEY);
        parameters.add("response_type", "token");
        parameters.add("redirect_uri", mRedirectUrl);
        parameters.add("display", "mobile");

//....
}

腾讯微博:不需要做任何的处理。

人人网:如果你使用的移动开发者平台,调用RMConnectCenter.logout()即可。如果你使用的第三方平台,调用Renren.logout()即可。

开心网:Kaixin类的authorize(...)方法下有一个判断session是否有效的方法,将这部分代码注释并且调用Kaixin.clearStorage(Context context).即可,需要注释部分的如下:

public void authorize(final Context context, String[] permissions,
			final KaixinAuthListener listener) {
//		if (this.isSessionValid()) {
//			listener.onAuthComplete(new Bundle());
//			return;
//		}
		this.authorize(context, permissions, listener, KX_AUTHORIZE_CALLBACK_URL, "token");
	}

 三:代码片段篇

1、返回Manifest文件中的版本号和版本名:

  Manifest文件中的manifest标签下的内容一般如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="yanbin.insertWeibo"
    android:versionCode="1"
    android:versionName="1.0" >

得到app版本号:

public static String getLocalVerCode(Context mContext){
		int versionCode = 0;
		PackageManager manager = mContext.getPackageManager();
		try {
			PackageInfo info = manager.getPackageInfo(mContext.getPackageName(), 0);
			versionCode = info.versionCode;  //版本号
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}	
		return String.valueOf(versionCode);
	}

得到app版本名:

public static String getVersionName(Context mContext){
		String str = "";
		PackageManager manager = mContext.getPackageManager();
		try {
			PackageInfo info = manager.getPackageInfo(mContext.getPackageName(), 0);
			str = info.versionName;   //版本名
		} catch (NameNotFoundException e) {
				e.printStackTrace();
		}	
		return str;
	}

2、addView(View child, int index, LayoutParams params)中index的含义

ViewGroup.java中对于addView(...)有很多的重载方法,其中有一个如下:

public void addView(View child, int index, LayoutParams params) {
        if (DBG) {
            System.out.println(this + " addView");
        }

        // addViewInner() will call child.requestLayout() when setting the new LayoutParams
        // therefore, we call requestLayout() on ourselves before, so that the child's request
        // will be blocked at our level
        requestLayout();
        invalidate();
        addViewInner(child, index, params, false);
    }

说一下其中index的含义,它表示要将当前的这个child子View添加到子View数组中的位置。如果你的值大于0,将插入到index位置,如果小于0,将插入到子view数组的末尾。其实就是调用了System.java类的System.arraycopy(...)这个静态方法来实现的。看一个System.arraycopy(...)的小例子:

public class ArrayCopyTest {
	public static void main(String[] args) {
		int index = 0;
		Integer arr[] = new Integer[]{1,2,3,4,5,6};
		Integer arrCopy[] = new Integer[arr.length + 1];
		System.arraycopy(arr, index, arrCopy, index + 1, arr.length);
	}
}

在Launcher程序中使用了这个addView(...)方法来实现往CellLayout中添加桌面元素。且元素默认是添加在末尾的。


 

抱歉!评论已关闭.