Android小经验

Posted 阿七不会写代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android小经验相关的知识,希望对你有一定的参考价值。

查看SQLite日志

1
2
adb shell setprop log.tag.SQLiteLog V
adb shell setprop log.tag.SQLiteStatements V

因为实现里用了Log.isLoggable(TAG, Log.VERBOSE)做了判断,LessCode的LogLess中也参考了这种机制:LogLess
使用这种方法就可以在Release版本也能做到查看应用的打印日志了。

PNG优化

APK打包会自动对PNG进行无损压缩,如果自行无损压缩是无效的。
当然进行有损压缩是可以的:https://tinypng.com/

Tcpdump抓包

有些模拟器比如genymotion自带了tcpdump,如果没有的话,需要下载tcpdump:
http://www.strazzere.com/android/tcpdump
把tcpdump push到/data/local下,抓包命令:

1
adb shell  /data/local/tcpdump -i any -p -s 0 -w /sdcard/capture.pcap

查看签名

很多开发者服务都需要绑定签名信息,用下面的命令可以查看签名:

1
keytool -list -v -keystore release.jks

注意,这个是需要密码的,可以查看MD5, SHA1,SHA256等等。

单例模式(懒汉式)的更好的写法

特别说到这个问题,是因为网上很多这样的代码:

1
2
3
4
5
6
7
8
9
10
11
public class Singleton 
    private static Singleton instance;
    private Singleton ()

    public static Singleton getInstance() 
        if (instance == null) 
            instance = new Singleton();
        
        return instance;
    

这种写法线程不安全,改进一下,加一个同步锁:

1
2
3
4
5
6
7
8
9
10
public class Singleton 
    private static Singleton instance;
    private Singleton ()
    public static synchronized Singleton getInstance() 
        if (instance == null) 
            instance = new Singleton();
        
        return instance;
    

网上这样的代码更多,可以很好的工作,但是缺点是效率低。
实际上,早在JDK1.5就引入volatile关键字,所以又有了一种更好的双重校验锁写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton 
    private volatile static Singleton singleton;
    private Singleton ()
    public static Singleton getSingleton() 
        if (singleton == null) 
            synchronized (Singleton.class) 
                if (singleton == null) 
                    singleton = new Singleton();
                
            
        
        return singleton;
    

注意,别忘记volatile关键字哦,否则就是10重,100重也可能还是会出问题。
上面是用的最多的,还有一种静态内部类写法更推荐:

1
2
3
4
5
6
7
8
9
10
publlic class Singleton 
    private Singleton() 
    private static class SingletonLoader 
        private static final Singleton INSTANCE = new Singleton();
    

    public static Singleton getInstance() 
        return SingletonLoader.INSTANCE;
    

多进程Application

是不是经常发现Application里的方法执行了多次?百思不得其解。
因为当有多个进程的时候,Application会执行多次,可以通过pid来判断那些方法只执行一次,避免浪费资源。

隐式启动Service

这是android5.0的一个改动,不支持隐式的Service调用。下面的代码在Android 5.0+上会报错:Service Intent must be explicit:

1
2
3
Intent serviceIntent = new Intent();
serviceIntent.setAction("com.jayfeng.MyService");
context.startService(serviceIntent);

可改成如下:

1
2
3
// 指定具体Service类,或者有packageName也行
Intent serviceIntent = new Intent(context, MyService.class);
context.startService(serviceIntent);

fill_parent的寿命

在Android2.2之后,支持使用match_parent。你的布局文件里是不是既有fill_parent和match_parent显得很乱?
如果你现在的minSdkVersion是8+的话,就可以忽略fill_parent,统一使用match_parent了,否则请使用fill_parent。

ListView的局部刷新

有的列表可能notifyDataSetChanged()代价有点高,最好能局部刷新。
局部刷新的重点是,找到要更新的那项的View,然后再根据业务逻辑更新数据即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
private void updateItem(int index) 
    int visiblePosition = listView.getFirstVisiblePosition();
    if (index - visiblePosition >= 0) 
        //得到要更新的item的view
        View view = listView.getChildAt(index - visiblePosition);

        // 更新界面(示例参考)
        // TextView nameView = ViewLess.$(view, R.id.name);
        // nameView.setText("update " + index);
        // 更新列表数据(示例参考)
        // list.get(index).setName("Update " + index);
    

强调一下,最后那个列表数据别忘记更新, 不然数据源不变,一滚动可能又还原了。

系统日志中几个重要的TAG

1
2
3
4
5
6
7
8
// 查看Activity跳转
adb logcat -v time | grep ActivityManager
// 查看崩溃信息
adb logcat -v time | grep AndroidRuntime
// 查看Dalvik信息,比如GC
adb logcat -v time | grep "D\\/Dalvik"
// 查看art信息,比如GC
adb logcat -v time | grep "I\\/art"

一行居中,多行居左的TextView

这个一般用于提示信息对话框,如果文字是一行就居中,多行就居左。
在TextView外套一层wrap_content的ViewGroup即可简单实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- 套一层wrap_content的ViewGroup -->
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/hello_world" />
    </LinearLayout>
</RelativeLayout>

setCompoundDrawablesWithIntrinsicBounds()

网上一大堆setCompoundDrawables()方法无效不显示的问题,然后解决方法是setBounds,需要计算大小…
不用这么麻烦,用setCompoundDrawablesWithIntrinsicBounds()这个方法最简单!

计算程序运行时间

为了计算一段代码运行时间,一般的做法是,在代码的前面加个startTime,在代码的后面把当前时间减去startTime,这个时间差就是运行时间。
这里提供一种写起来更方便的方法,完全无时间逻辑,只是加一个打印log就够了。

1
2
3
4
// 测试setContentView()的时间
Log.d("TAG", "Start");
setContentView(R.layout.activity_http);
Log.d("TAG", "End");

没有计算时间的逻辑,这能测出来?
把日志过滤出来,运行命令“adb logcat -v time | grep TAG”:

1
2
03-18 14:47:25.477 D/TAG     (14600): Start
03-18 14:47:25.478 D/TAG     (14600): End

通过-v time参数,可以比较日志左边的时间来算出中间的代码运行的时间。

JAVA引用类型一览表

对象引用:强引用 > 软引用 > 弱引用 > 虚引用。

引用类型 回收时机 用途 生存时间
强引用 从来不会 对象的一般状态 JVM停止运行时终止
软引用 在内存不足时 对象缓存 内存不足时终止
弱引用 在垃圾回收时 对象缓存 GC运行后终止
虚引用 在垃圾回收时 对象跟踪 GC运行后终止

Context使用场景

为了防止Activity,Service等这样的Context泄漏于一些生命周期更长的对象,可以使用生命周期更长的ApplicationContext,但是不是所有的Context的都能替换为ApplicationContext
这是网上流传的一份表格:

  Application Activity Service ContentProvider BroadcastReceiver
Show Dialog
Start Activity
android应用刷新系统多媒体库(增加or删除多媒体文件)

Android开发本地及网络Mp3音乐播放器(十九)通知媒体库更新刚下载的MP3

如何扫描出Android系统媒体库中视频文件

Cordova 和 3PP 原生媒体播放器库在 Android 中提供致命信号 11

Android小经验

Android加入新的视频格式--媒体库扫描

(c)2006-2024 SYSTEM All Rights Reserved IT常识