总结一下Android编码时的一些技巧

1.高效的返回一个带泛型的空集合java
Collections. emptyList()
2.判断当前集合size是否为空
Collection.isEmpty()
3.SharedPreferences清空Key值下的数据
SharedPreferences.Editor editor = userSettings.edit();
editor.remove("KEY");
editor.commit();
4.SharedPreferences清空文件数据
SharedPreferences.Editor editor = userSettings.edit();
editor.clear();
editor.commit();
5.git 修改.git ignore后生效

在使用git的时候我们有时候需要忽略一些文件或者文件夹。我们一般在仓库的根目录创建.gitignore文件

*.iml
.gradle
/local.properties
/.idea/
/app/mapping.txt
/build/
/app/build/
/app/release/
/app/debug/

在提交之前,修改.gitignore文件,添加需要忽略的文件。然后再做add commit push 等

但是有时在使用过称中,需要对.gitignore文件进行再次的修改。这次我们需要清除一下缓存cache,才能是.gitignore 生效。

具体做法:

git rm -r --cached .  #清除缓存
git add . #重新trace file
git commit -m "update .gitignore" #提交和注释
git push origin master #可选,如果需要同步到remote上的话

这样就能够使修改后的.gitignore生效。

6.Android中使用注解替代枚举
public class Constants {
    public static final int STATE_ONE = 1;
    public static final int STATE_TWO = 2;
    public static final int STATE_THREE = 3;

    // 自定义一个注解MyState
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({STATE_ONE, STATE_TWO, STATE_THREE})
    public @interface  MyState {}
}

状态变量:

@Constants.MyState
private int state;

赋值

private void setState(@Constants.MyState int state) {
    //some code
}
7.RxJava实现倒计时
import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;

public class SplashActivity extends BaseActivity {
   
    private Disposable mDisposable;
    
    @Override
    protected void setListener() {
    	//在需要的时候创建
        mDisposable = Flowable.intervalRange(0, 5, 0, 1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .doOnNext(aLong -> {
                //倒计时读秒
                })
                .doOnComplete(//倒计时结束)
                .subscribe();
    }
    @Override
    protected void onDestroy() {
       	closeTimeDown();
        super.onDestroy();
    }
    private void closeTimeDown() {
        if (null != mDisposable && !mDisposable.isDisposed()) {
            mDisposable.dispose();
            mDisposable = null;
        }
    }
}
8.关于List的局部移除

根据位置移除
position:开始位置
position + count:结束位置(不包含此位置数据)

List.subList(position, position + count).clear();

根据条件移除

List<String> list = new ArrayList<>(); 
list.add("1");
list.add("2");
Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) {
	String item = iterator.next(); 
	if (删除元素的条件) {
		iterator.remove(); 
	}
} 
9.相关类在Java8中的替代

如果是 JDK8 的应用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar, DateTimeFormatter 代替 SimpleDateFormat,官方给出的解释:simple beautiful strong immutable thread-safe

volatile 解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题, 但是如果多写,同样无法解决线程安全问题。如果是 count++操作,使用如下类实现: AtomicInteger count = new AtomicInteger(); count.addAndGet(1); 如果是 JDK8,推 荐使用 LongAdder 对象,比 AtomicLong 性能更好(减少乐观锁的重试次数)

10.IntentService的使用

避免在 Service#onStartCommand()/onBind()方法中执行耗时操作,如果确 实有需求,应改用 IntentService 或采用其他异步机制完成。

public class MainActivity extends Activity {
	@Override
	public void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState); setContentView(R.layout.main);
	}
	public void startIntentService(View source) {
		Intent intent = new Intent(this, MyIntentService.class);
		startService(intent); 
	}
	
}

public class MyIntentService extends IntentService {
	public MyIntentService() {
		super("MyIntentService"); 
	}
	@Override
	protected void onHandleIntent(Intent intent){
		synchronized (this) {
			try {
				......
			} catch (Exception e) {
			} 
		}
	} 
}
11.避免在 BroadcastReceiver#onReceive()中执行耗时操作

避免在 BroadcastReceiver#onReceive()中执行耗时操作,如果有耗时工作, 应该创建 IntentService 完成,而不应该在 BroadcastReceiver 内创建子线程去做。
说明:
由于该方法是在主线程执行,如果执行耗时操作会导致 UI 不流畅。可以使用 IntentService 、 创建 HandlerThread或者调用 Context#registerReceiver
(BroadcastReceiver, IntentFilter, String, Handler)方法等方式,在其他 Wroker 线程
执行 onReceive 方法。BroadcastReceiver#onReceive()方法耗时超过 10 秒钟,可
能会被系统杀死。
正例:

IntentFilter filter = new IntentFilter(); 
filter.addAction(LOGIN_SUCCESS); 
this.registerReceiver(mBroadcastReceiver, filter); 
mBroadcastReceiver = new BroadcastReceiver() {
	@Override
	public void onReceive(Context context, Intent intent) {
		Intent userHomeIntent = new Intent(); 
		userHomeIntent.setClass(this, UseHomeActivity.class); 
		this.startActivity(userHomeIntent); 
	}
};
12.避免在 Activity#onDestroy() 内执行释放资源

不要在 Activity#onDestroy()内执行释放资源的工作,例如一些工作线程的 销毁和停止,因为 onDestroy()执行的时机可能较晚。可根据实际需要,在 Activity#onPause()/onStop()中结合 isFinishing()的判断来执行。

13.再说一下编码时相关的命名规范

类名使用 UpperCamelCase 风格,方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格。

常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。

包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用 单数形式,但是类名如果有复数含义,类名可以使用复数形式。

抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类命名以它要测试的类的名称开始,以 Test 结尾。

POJO 类中布尔类型的变量,都不要加 is 前缀。

如果模块、接口、类、方法使用了设计模式,在命名时需体现出具体模式。

接口类中的方法和属性不要加任何修饰符号,尽量不要在接口里定义变量,如果一定要定义变量,肯定是与接口方法相关,并且是整个应用的基础常量。

接口的命名
(1)Service 和 DAO 类:CacheServiceImpl 实现 CacheService 接口
(2)形容能力的接口:AbstractTranslator 实现 Translatable 接口。

枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。

14.MacOS 下 adb 指令无法识别

首先确保adb环境变量已经配置

  • 1.打开终端输入命令行输入 open .zshrc 回车。
  • 2.打开的文件中找到 # User configuration 部分,紧贴其后添加 source ~/.bash_profile。
  • 3.点击文件的完成,命令行再输入source .zshrc 回车。
  • 4.在执行adb命令成功解决。
15.MacOS 下 拷贝android数据库到电脑
  • 1.插入设备,然后从命令行或终端运行 adb shell。
  • 2.在 shell 中 run-as com.myapplication.packagname(你想要拷贝的包名)。
  • 3.然后 CD 进入数据库文件夹 cd databases。
  • 4.然后运行 cat my_datbase_name.db(数据库名) > /sdcard/my_database_name_temp.db(拷贝的数据库名)。
  • 5.运行exit ,然后再次 exit 以返回正常的终端提示符。
  • 6.cd 到指定目录,运行 adb pull /sdcard/my_database_name_temb.db ,OK!
16.kotlin下的enum和enum的替代
enum class ColorEnum(val typeId: Int) {
   NULL(0),
   GREEN(1),
   RED(2);
    companion object {
        fun parseFromInt(id: Int) = values().find { it.typeId == id} ?: NULL
    }
}
sealed class NetworkState {

    object Loading : NetworkState()
    object Success : NetworkState()

    data class Error(
            val code: Int? = null,
            val heading: Int? = null,
            val message: Int? = null
    ) : NetworkState()

    var optionCallback: ((pos: Int) -> Unit)? = null
    var optionCallbackNoParam: (() -> Unit)? = null

}
17.为TextView自适应TextSize
  <androidx.appcompat.widget.AppCompatTextView
                    android:id="@+id/cloudRecordUpgradeTip1"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="40dp"
                    android:layout_marginTop="28dp"
                    android:ellipsize="end"
                    android:gravity="center_vertical"
                    android:lines="1"
                    android:text="@string/cloud_record_setting_upgrade_tip1"
                    android:textColor="#FF7777"
                    android:textSize="18sp"
                    app:autoSizeMaxTextSize="18sp"
                    app:autoSizeMinTextSize="12sp"
                    app:autoSizeStepGranularity="2sp"
                    app:autoSizeTextType="uniform"
                   />
18.为TextView设置drawable
drawable.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight)
textView.setCompoundDrawables(null, null, drawable, null)

可以封装成一个ViewExt方法

fun TextView.endIcon(@DrawableRes res: Int = 0, ctx: Context = app) = apply {
    if (res != 0) {
        ContextCompat.getDrawable(ctx, res)?.let { drawable ->
            drawable.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight)
            setCompoundDrawables(null, null, drawable, null)
        }
    } else {
        setCompoundDrawables(null, null, null, null)
    }
}
19.map 遍历 remove
val iterator = dataMap.entries.iterator()
while (iterator.hasNext()) {
    val item = iterator.next()
    if (strs.contains(item.key)) {
           iterator.remove()
    }
}
20.震动
        getSystemService(VIBRATOR_SERVICE) as? Vibrator
        val pattern = longArrayOf(500, 1000, 500, 1000)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
           val vibe = VibrationEffect.createWaveform(pattern, 0)
            vibrator.vibrate(vibe)
        } else {
            vibrator.vibrate(pattern, 0)
        }
21.tint在android 5.0上的使用
<?xml version="1.0" encoding="UTF-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/card_info_setting_btn"
    android:tint="#80FFFFFF"
    android:tintMode="multiply">
</bitmap>
22.Sequence让集合处理更高效
    private fun computeRunTime(action: (() -> Unit)?) {
        val startTime = System.currentTimeMillis()
        action?.invoke()
        println("the code run time is ${System.currentTimeMillis() - startTime}")
    }
    private val computeIteratorRunTime={
        (0..10000000)
                .map { it + 1 }
                .filter { it % 2 == 0 }
                .count { it < 10 }
                .run {
                    println("by using sequences way, result is : $this")
                }
    }
    //转化成Sequences序列,使用序列操作
   private val computeSequenceRunTime ={
        (0..10000000)
                .asSequence()
                .map { it + 1 }
                .filter { it % 2 == 0 }
                .count { it < 10 }
                .run {
                    println("by using sequences way, result is : $this")
                }
    }
23.不同文字颜色和大小

使用SpannableStringBuilder

    fun messageNumToFormatText2(num: Int,strRes:Int): SpannableStringBuilder {
        val startStr = num.toString()
        val str = Utils.getString(strRes, startStr)
        return SpannableStringBuilder(str).apply {
            setSpan(ForegroundColorSpan(Color.parseColor("#2B2D2F")), 0, startStr.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            setSpan(AbsoluteSizeSpan(40, true), 0, startStr.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            setSpan(ForegroundColorSpan(Color.parseColor("#7A7E8E")), startStr.length, str.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            setSpan(AbsoluteSizeSpan(9, true), startStr.length, str.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        }
    }

使用Html的string

<string name="stringName1"><![CDATA[<html>bla</html>]]></string>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值