Android小知识清单(一)

  在公司多人协作写代码最怕的就是冲突。。。因此一定要协作好,必须有规范,比如引用的库v4、v7包版本都要一致等等。

1、invalidate()和postInvalidate()有什么区别?

        对于invalidate()源码注释如下:

     *Invalidate the whole view. If the view is visible,
     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
     * the future. This must be called from a UI thread. To call from a non-UI thread,
     * call {@link #postInvalidate()}. 

   即该方法会导致整个View都无效,然后会调用onDraw()方法,且该方法必须在主线程中使用,如果需要在子线程中调用,我们通常的做法是使用Thread+Handler来完成invalidate()调用,或者使用postInvalidate()方法,此方法可以直接在子Thread中使用。这就是两者的区别。需要注意的是,如果是在View中调用那么会导致该View被绘制,而其它视图不会被绘制,如果是在ViewGroup中调用这两个方法那么会导致该ViewGroup下的所有子视图重绘。

2、Parcelable接口有什么用?

      此接口源码解释如下:

* Interface for classes whose instances can be written to
 * and restored from a {@link Parcel}.  Classes implementing the Parcelable
 * interface must also have a static field called <code>CREATOR</code>, which
 * is an object implementing the {@link Parcelable.Creator Parcelable.Creator}
 * interface.
 *
       此接口用于序列化和反序列化数据,而且性能较Serializable稍微高一些,不过实现也稍微多一个步骤,注释中已有说明,且源码还有一个例子,就不贴出来了。值得思考的是Android为什么引进一个Parcelable接口呢?我猜测主要还是基于性能考虑吧,Ctrl+T发现framework中实现此接口的类有很多,我目测了下,至少有好几十个类。典型的有Bundle和ContentValues,所以在Intent传递数据的时候我们可以直接传递ContentValues,可以直接intent.putExtra(key,cv),获取时intent.getExtras().get(key)。。。etc.  跑题了!。。那么framework中有这么多类都需要序列化存储数据,为了提高性能,是很有值得引入一个接口代替Serializable了。实际上Serializable接口中没啥内容,要被序列化的类实现此接口不过是一个标识,标识该类可以被序列化。同理Parcelable接口也是一样,不过在序列化时能提高性能,具体没有研究 - -、,以后有时间了再仔细瞅瞅。

3、xml布局文件中的"?"和"@"的区别?

  “?”引用主题属性,当使用这个标记,我们所提供的资源名必须能够在主题属性中找到,因为资源工具认为这个资源属性是被期望得到的,我们不需要明确的指出它的类型(也就是不需要写全在哪个文件中?android:attr/android:textDisabledColor)。

  @表示引用资源文件中我们定义的内容drawable、string等,主题属性和样式属性只是使用范围不同而已,效果差不多,系统的主题属性有:http://android.toolib.net/reference/android/R.styleable.html#Theme

4、如何在xml中使用自定义视图的属性?

    如果在xml中要引用自定义控件的属性,必须在xml命名空间引用,比如:xmlns:bar="http://schemas.android.com/apk/res/com.geo.ui",和系统的属性引用一样只不过在res目录后加上自己程序的包名,这个包名不是自定义控件所在的包名,而是在androidmanifest.xml 文件中的package属性的名字,这个包名就是应用程序的进程名字。当然了“bar”这个名字随意起。

5、java中map、list如何更快创建对象并添加数据?

public static HashSet<String> sDocMimeTypesSet = new HashSet<String>() {        
{           
 add("text/plain");           
 add("text/plain");            
add("application/pdf");            
add("application/msword");           
 add("application/vnd.ms-excel");           
 add("application/vnd.ms-excel");      
  }  
  };

6、ActionMode是什么?

    ActionMode是4.0后新特性,表示长按某个视图就会出现类似菜单上下文的菜单,但不是弹窗,而是在ActionBar上面显示。要使用ActionMode需要先实现ActionMode.CallBback接口,然后在Activity中调用startActionMode(),或在Fragment中调用getActivity().startActionMode();

7、SQLiteOpenHelper的onCreate()方法调用问题。

    SQLiteOpenHelper的onCreate()方法只在数据库第一次被创建的时候调用一次,如果该数据库已经存在就不会重复调用了。因此,如果我们在一个已有的数据库中新增一个表,就需要在onUpgrade(SQLiteDatabase,int,int)中做数据库升级。当我们要对数据库升级的时候,仅仅在onCreate(SQLiteDatabase db)方法中增加一条sql语句和修改版本号是不够的,还要在onUpgrade()函数中增加要升级的sql语句,不然会导致升级失败,项目中遇到这个坑。比较详细的看此博客:http://www.cnblogs.com/liqw/p/4264925.html

   public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub
        try {
            db.execSQL("drop table if exists "+mTableName);
            
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

8、ConcurrentHashMap是个什么?

    ConcurrentHashMap的在并发情况下使用的HashMap。普通的HashMap在并发情况下使用put方法会容易引起死循环。关于并发如下:http://ifeve.com/concurrenthashmap/

9、Date的日期如何比较?

    Date的日期比较:date1.after(date2)表示的是如果date1在date2之后就返回true,比如date1=2015-01-23,date2=2014-12-25,结果返回true,此时如果是date1.before(date2)将会返回false.此外,讲一个字符串的时间转换为Date直接用new SimpleDateFormat("....").parse("...");都是些无关痛痒的小问题,不过还是习惯记录下。

10、如何解决ScrollVIew和ListView的冲突?

    /**  
     * 重新计算ListView的高度,解决ScrollView和ListView两个View都有滚动的效果,在嵌套使用时起冲突的问题  
     * @param listView  
     */  
    public void setListViewHeight(ListView listView) {    
            
        // 获取ListView对应的Adapter    
        
        ListAdapter listAdapter = listView.getAdapter();    
        
        if (listAdapter == null) {    
            return;    
        }    
        int totalHeight = 0;    
        for (int i = 0, len = listAdapter.getCount(); i < len; i++) { // listAdapter.getCount()返回数据项的数目    
            View listItem = listAdapter.getView(i, null, listView);    
            listItem.measure(0, 0); // 计算子项View 的宽高    
            totalHeight += listItem.getMeasuredHeight(); // 统计所有子项的总高度    
        }    
        
        ViewGroup.LayoutParams params = listView.getLayoutParams();    
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));    
        listView.setLayoutParams(params);    
    }

    ScrollView只能有一个子View。需要注意的是子ListView的每个Item必须是LinearLayout,不能是其他的,因为其他的Layout(如RelativeLayout)没有重写onMeasure(),所以会在onMeasure()时抛出异常。原文在此http://blog.csdn.net/wulianghuan/article/details/8627958。其实也可以重写一个ListView,只需要重写其onMeasure()方法。


11、Eclipse非正常性错误。

    从我电脑上拷了Android项目到公司电脑上的Eclipse的workeplace,出现overlaps the location of another project: 'XXX'错误,项目重复了。貌似是Eclipse在导入创建项目的时候会创建同名的目录,因此会报错,我把项目放在非workplace目录可以正常导入,但是我的项目引用了workplace中的其他项目!导致项目虽然能够正常导入但是不能正常使用,因此我在workplace中再建一个目录用于放我导入的项目,这一次就ok了!

12、EditText如何在代码中设置成密码形式?

    使用代码将EditText设置为密码形式:inputEt.setTransformationMethod(PasswordTransformationMethod.getInstance());

13.获取手机屏幕分辨率(高和宽)的方法?:

public static float[] getWHofDevice(Activity ac){
		 float[] wh = new float[2];
		 //Display用于展示尺寸和密度的类
		 Display display = ac.getWindowManager().getDefaultDisplay(); 
		 //Point类封装了座标系的X轴和Y轴两个座标点
		 Point size = new Point();
		 display.getSize(size);
		 wh[0] = size.y;
		 wh[1] = size.x;
		 return wh;
	 }

    当然了,也可以用一下方法:

        Display diaplay = getWindowManager().getDefaultDisplay();
        Point point = new Point();
        diaplay.getSize(point);
        int x = point.x;
        int y = point.y;

14、MotionEvent的getRowX()和getX()的区别?

    MotionEvent的getRowX()表示获取的是滑动的相对屏幕的X轴座标,getX()表示相对于被滑动的View的座标,getX()的值不会超过该VIew的宽,getY()和getRowY()同理。

15、ListView的Item设置Selector不起作用?

    在ListView的Item的控件上设置Selector必须对该控件设置一个clickable属性为true才有效,否则设置会不起作用。

16、自定义视图重写onMeasure()不调用setMeasureDimension()?

    自定义视图中,当重写onMeasure()方法时,如果不super.onMeasure(),那么就必须设置setMeasuredDimension(width, height);的值。

17、View的post()和Handler的post()区别?

    关于View的post()方法和Handler的post()、sendMessage(..)的方法的比较,实际上View的post()方法都是调用了Handler的post()或postDelay()方法,而Handler的post()方法最终还是调用它自己的sendMessageAtTime()方法。

18、没事就看看别人项目源码呗:

    http://blog.csdn.net/shimiso/article/details/14522093

19、AndroidStudio启动报IllegalArgumentException错误?错:java.lang.RuntimeException: java.lang.IllegalArgumentException: Argument for @NotNull parameter 'name' of com/android/tools/idea/welcome/Platform.<init> must not be null,在网上搜到的解决方案:

    1)进入刚安装的Android Studio目录下的bin目录。找到idea.properties文件,用文本编辑器打开。
    2)在idea.properties文件末尾添加一行: disable.android.first.run=true ,然后保存文件。
    3)关闭Android Studio后重新启动,便可进入界面。、

20、.在做适配的时候报错Resources$NotFoundException

    在做适配的时候报错:android.content.res.Resources$NotFoundException: File res/drawable-hdpi/expanded.PNG from drawable resource ID #0x7f02007d: .xml extension required。已经解决,http://www.360doc.com/content/12/1205/14/1801810_252271083.shtml

21、Adapter的getView()方法的position总是返回0?

    Adapter的getView()方法的position总是返回0,明明有很多item,但是返回的总是0,原因是这些item中的高度是不同的,在变化,这导致ListView重绘了。

22、如何摆脱使用findViewById的困扰?

      1创建一个基类,BaseActivity并继承Activity

      方法如下:

public class BaseActivity extends Activity {

  @Override

  protected void onCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);

  }

  protected <T extends View> T generateFindViewById(int id) {

      //return返回view时,加上泛型T

      return (T) findViewById(id);

  }

}

      2自己写的Activity都去继承BaseActivity

之后我们自己写的每一个Activity都去继承BaseActivity,然后在初始化控件时直接使用generateFindViewById来代替findViewById即可。

23、如何更方便的在子线程创建Looper

    有时候我们需要在子线程中创建Handler对象,我们知道,在线程中创建Handler的时候必须保证当前线程有Looper对象,因此通常需要在run方法中调用prepare()和loop,其实有一种更方便的用法来创建Loop,那就是使用HandlerThread实现,HandlerThrtead是SDK提供的一个简单的类,用法如下:

    (1)创建HandlerThread对象:HandlerThread handlerThread = new HandlerThread("my_handler");

    (2)调用start方法:handlerThread.start();

    (3)创建Handler:Handler handler = new Handler(handlerThread.getLooper());如此即可。

24、如何监听文件/目录的变化

    有时候我们需要监听手机上指定的目录或文件的变化,如被删除、被修改或新增了文件等,这种变化需要我们的app随时知道,应该怎么实现呢?SDK提供了一个FileObserver类给我们,可以很容易的实现:

   (1)继承FileObserver类实现其抽象方法来完成自己的FileObserver。

   (2)为指定目录/文件添加监听:添加监听其实就是在创建FileObserver对象的时候传递路径:

				FileObserver mFrameworkInstallObserver = new AppDirObserver(
						mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
    其中的mFrameworkDir.getPath()就是监听system/app目录。

   (3)启动监听:mFrameworkInstallObserver.startWatching();

25、Android如何缓存数据

    可以使用Android自带的LruCache或者使用轻量级的ACache(网上搜).

26、ImageView在布局文件会出现空白的问题

    在布局文件的ImageView标签中加入android:adjustViewBounds="true"或者在代码中设置ImageView.setAdjustViewBounds(true)即可。

27、关于TextView的一些属性用法

     首先需要继承TextView,什么也不用干,就把isFocused()返回true即可。

   (1)限制文本长度:android:maxEms="6",最长只能显示6个字符。

   (2)跑马灯x效果:android:singleLine="true",android:ellipsize="marquee"

   (3)当然我们也可以在代码中设置:tv.setEllipsize(TruncateAt.MARQUEE);

28、关于EditText的一些属性用法

   (1)设置多行显示,类似html的textarea:android:lines="4",显示四行,

   (2)如果lines是多行,光标显示在第一行: android:lines="4",android:gravity="top",这样就行了。

29、什么时候用关键字static来修饰属性、方法?

    “你的属性或方法是否需要在没有对象的情况下使用?如果是那么就该用static了,如果不是那么就别用static了。”。

30、LIstView单击item无响应的问题

    主要是焦点问题,这里就需要用到android:descendantFocusability属性了,详见此博客http://www.cnblogs.com/eyu8874521/archive/2012/10/17/2727882.html ;   。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章