Throwable类中的getStackTrace()方法,根据这个方法能够获得函数的逐层调用地址,其返回值为StackTraceElement[],而在StackTraceElement类中有四个方法getClassName(),getFileName(),getLineNumber(),getMethodName()在调试程序打印Log时很是有用。android
try {
int num = 1 / 0;
} catch (Exception e) {
e.printStackTrace();
StackTraceElement[] stackTrace = e.getStackTrace();
for (StackTraceElement element : stackTrace) {
String className = element.getClassName();
int lineNumber = element.getLineNumber();
String fileName = element.getFileName();
String methodName = element.getMethodName();
Log.e("TAG", "fileName:" + fileName + " lineNumber:" + lineNumber + " className:" + className + " methodName" + methodName);
}
}
public class CrashHandler implements Thread.UncaughtExceptionHandler {
private static final String TAG = CrashHandler.class.getSimpleName();
private Context mContext;
private static volatile CrashHandler instance;
private Thread.UncaughtExceptionHandler defalutHandler;
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss.SSS", Locale.CHINA);git
private CrashHandler() {
}web
/**
* 得到单例 * @return 单例
*/
public static CrashHandler getInstance() {
if (instance == null) {
synchronized (CrashHandler.class) {
if (instance == null) {
instance = new CrashHandler();
}
}
}
return instance;
}算法
public void init(Context context) {
mContext = context.getApplicationContext();
defalutHandler = Thread.getDefaultUncaughtExceptionHandler(); // 获取系统默认的UncaughtException处理器
Thread.setDefaultUncaughtExceptionHandler(this); // 设置该CrashHandler为程序的默认处理器
}数据库
@Override
public void uncaughtException(Thread thread, Throwable ex) {
boolean hasHandle = handleException(ex); //是否处理
if (!hasHandle && defalutHandler != null) {
defalutHandler.uncaughtException(thread, ex); //若是用户没有处理则让系统默认的异常处理器来处理
} else {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Log.e(TAG, "error : ", e);
}
android.os.Process.killProcess(android.os.Process.myPid());
system.exit(1);
}
}canvas
private boolean handleException(final Throwable ex) {
if (ex == null) {
return false;
}
new Thread() {
@Override
public void run() {
Looper.prepare();
}
ex.printStackTrace();
String err = "[" + ex.getmessage() + "]";
Toast.makeText(mContext,"程序出现异常,5秒后自动退出",Toast.LENGTH_LONG).数组
show();
Looper.loop();
}.start();浏览器
String str = collectDeviceInfo(ex); // 收集设备参数信息,日志信息 缓存
saveCrashInfoToFile(str); // 保存日志文件
return true;
}安全
/**
* 收集设备信息,日志信息 * @param ex Throwable * @return 收集的信息
*/
private String collectDeviceInfo(Throwable ex) {
Log.e(TAG, "collectDeviceInfo:" + ex.getMessage());
StringBuilder builder = new StringBuilder();
return builder.toString();
}
/**
* 保存出错信息 * @param error 待保存的出错信息
*/
private void saveCrashInfoToFile(String error) {
Log.e(TAG, "saveCrashInfoToFile:" + error);
}
}
程序入口进行初始化,以后未捕获的异常均由此类处理。
CrashHandler.getInstance().init(this);
Resources类中的getIdentifier(name, defType, defpackage)方法,根据资源名称获取其ID,作UI时常常用到。
好比得到主布局的idResourcesUtil.getResourceId(getApplicationContext(),"activity_main",ResourcesUtil.LAYTOUT);
android.text.format.Formatter类中formatFileSize(Context, long)方法,用来格式化文件大小(B → KB → MB → GB)
android.text.format.Formatter.formatFileSize(getApplicationContext(),1024); //返回1.00KB
android.media.ThumbnailUtils类,用来获取媒体(图片、视频)缩略图,该类从Android 2.2开始系统新增,不向下兼容
/** * 建立一张视频的缩略图 * 若是视频已损坏或者格式不支持可能返回null * *
@param filePath 视频文件路径 如:/sdcard/android.3gp *
@param kind kind能够为MINI_KIND或MICRO_KIND * */
ThumbnailUtils.createVideoThumbnail(filePath,kind);
/** * * 建立一个指定大小的缩略图 *
@param source 源文件(Bitmap类型) *
@param width 压缩成的宽度 *
@param height 压缩成的高度 */
ThumbnailUtils.extractThumbnail(source , width, height);
/** * 建立一个指定大小居中的缩略图 * *
@param source 源文件(Bitmap类型) *
@param width 输出缩略图的宽度 *
@param height 输出缩略图的高度 *
@param options 若是options定义为OPTIONS_RECYCLE_INPUT,则回收@param source这个资源文件 * (除非缩略图等于@param source) * */
ThumbnailUtils.extractThumbnail(source , width, height,options);
格式化字符串,可使用String类的format(String,Object…)方法,若是要格式化资源文件strings.xm
TextUtils类中的isEmpty(String)方法,判断字符串是否为null或”“,不要再本身写判断字符串非空的代码了。
String str = null; String str1 = "";
String str2 = "a";
Log.e("TAG", TextUtils.isEmpty(str)+" "+TextUtils.isEmpty(str1)+" "+TextUtils.isEmpty(str2)); //输出true true false
相似的方法还有TextUtils.isDigitsOnly()是不是纯数字
View类中的getDrawingCache()等一系列方法,目前只知道能够用来截图
/**
* / 获取指定Activity的截屏,保存到png文件 * * @param activity activity * @return 截屏Bitmap
*/
private static Bitmap takeScreenShot(Activity activity) { // View是你须要截图的
View View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap b1 = view.getDrawingCache();
// 获取状态栏高度
Rect frame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
Log.i("TAG", "" + statusBarHeight);
// 获取屏幕长和高
int width = activity.getWindowManager().getDefaultDisplay().getWidth();
int height = activity.getWindowManager().getDefaultDisplay().getHeight();
Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height - statusBarHeight);
view.destroyDrawingCache();
return b;
}
System类中的arraycopy(src, srcPos, dest, destPos, length)方法,用来copy数组;Arrays.copyOf()里的一系列方法也是间接调用System.arraycopy()方法
Fragment类中的onHiddenChanged(boolean)方法,使用FragmentTransaction中的hide(),show()时貌似Fragment的其它生命周期方法都不会被调用
调用hide或者show你就会发现fragment的生命周期不走了!onPause方法不调用了!onResume只调用一次!这时此时方法onHiddenChanged派上用场
当fragment隐藏时,该方法会调用传入参数为true表示该fragment被隐藏了, 当fragment调用了show方法后,该方法传入的参数为false,表示该fragment正在显示
因此总结起来,若是使用hide/show方法来控制fragment的使用时,本来须要在onResume以及onPause方法作的事情就能够迁移到onHiddenChanged时进行管理
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (hidden) {
this.onPause();
} else {
this.onResume();
}
}
Activity类中的onWindowFocusChanged(boolean)方法,使用一个view的getWidth() getHeight() 方法来获取该view的宽和高,返回的值却为0。
若是这个view的长宽很肯定不为0的话,那极可能是你过早的调用这些方法,也就是说在这个view被加入到rootview以前你就调用了这些方法,返回的值天然为0.,解决该问题的方法有不少,主要就是延后调用这些方法。能够试着在onWindowFocusChanged()里面调用这些方法。
View类中的getLocationInWindow(int[])方法和getLocationOnScreen(int[])方法,获取View在窗口/屏幕中的位置
TextView tv= (TextView) findViewById(R.id.tv); int loc[]=new int[2]; tv.getLocationInWindow(loc); Log.e("TAG",loc[0]+" "+loc[1]);
TextView类中的setTransformationMethod(TransformationMethod)方法,可用来实现“显示密码”功能;
TextView tv= (TextView) findViewById(R.id.tv); tv.setText("123456"); tv.setTransformationMethod(PasswordTransformationMethod.getInstance());
TextView.setError() 在验证用户输入的时候很棒
Linkify.addLinks() 在Text上添加连接。很实用。好比将TextView中的超连接识别为可点击进入浏览器的连接。
TextView tv= (TextView) findViewById(R.id.tv); Linkify.addLinks(tv,Linkify.WEB_URLS);
ListView或GridView类中的setFastScrollEnabled(boolean)方法,用来设置快速滚动滑块是否可见,固然前提是item够多
PageTransformer接口,用来自定义ViewPager页面切换动画,用setPageTransformer(boolean, PageTransformer)方法来进行设置
Activity类中的onNewIntent(intent)方法,具体看这篇文章Android:onNewIntent()触发机制及注意事项
Html.fromHtml() 用于生成一个Html,参数能够是一个字符串.可是它不是很快,因此不要常常去用.取而代之的是请手动构建 Spannable 来替换 Html.fromHtml,可是它对渲染从 web 上获取的文字仍是很不错的。
Build.version_CODES 这个标明了当前的版本号,在处理兼容性问题的时候常常会用到.点进去能够看到各个版本的不一样特性
ViewConfiguration.getScaledTouchSlop() 使用 ViewConfiguration 中提供的值以保证全部触摸是的交互都统一的。
这个方法获取的值表示:用户的手滑动这个距离后,才断定为正在进行滑动.固然这个值也能够本身来决定.可是为了一致性,仍是使用标准的值较好。
PhoneNumberUtils.convertKeypadLettersToDigits 顾名思义.将字母转换为数字,相似于T9输入法
String abcd = PhoneNumberUtils.convertKeypadLettersToDigits("abcd"); Log.e("TAG",abcd); //结果为2223
Context.getCacheDir() 获取缓存数据文件夹的路径,这个路径一般在SD卡上(这里的SD卡指的是广义上的SD卡,包括外部存储和内部存储)Adnroid/data/您的应用程序包名/cache/ 下面.测试的时候,能够去这里面看是否缓存成功.缓存在这里的好处是:不用本身再去手动建立文件夹,不用担忧用户把本身建立的文件夹删掉,在应用程序卸载的时候,这里会被清空,使用第三方的清理工具的时候,这里也会被清空。
ArgbEvaluator 用于处理颜色的渐变。在使用动画的时候可能用的比较多。能够看下他的实现
public Object evaluate(float fraction, Object startValue, Object endValue) {
int startInt = (Integer) startValue;
int startA = (startInt >> 24) & 0xff;
int startR = (startInt >> 16) & 0xff;
int startG = (startInt >> 8) & 0xff;
int startB = startInt & 0xff;
int endInt = (Integer) endValue;
int endA = (endInt >> 24) & 0xff;
int endR = (endInt >> 16) & 0xff;
int endG = (endInt >> 8) & 0xff;
int endB = endInt & 0xff;
return (int) ((startA + (int) (fraction * (endA - startA))) << 24) | (int) ((startR + (int) (fraction * (endR - startR))) << 16) | (int) ((startG + (int) (fraction * (endG - startG))) << 8) | (int) ((startB + (int) (fraction * (endB - startB))));
}
Space 它是Android 4.0中新增的一个控件,它实际上能够用来分隔不一样的控件,其中造成一个空白的区域.这是一个轻量级的视图组件,它能够跳过Draw,对于须要占位符的任何场景来讲都是很棒的。
<Space android:layout_width="match_parent" android:layout_height="10dp"/>
ValueAnimator.reverse() 用在动画中,将动画逆向。
EditText类的setKeyListener(KeyListener)方法,设置DigitsKeyListener类将只能输入数字,经过DigitsKeyListener.getInstance(String accepted)方法便可指定EditText可输入的字符集。
DateUtils.formatDateTime() 用来进行区域格式化工做,输出格式化和本地化的时间或者日期。
android.text.format.DateUtils.formatDateTime(getApplicationContext(),System.currentTimeMillis(), DateUtils.FORMAT_SHOW_DATE|DateUtils.FORMAT_SHOW_YEAR|DateUtils.FORMAT_SHOW_TIME);
StaticLayout 在自定义 View 中渲染文字的时候很实用。
使用Canvas的drawText绘制文本是不会自动换行的,即便一个很长很长的字符串,drawText也只显示一行,超出部分被隐藏在屏幕以外。能够逐个计算每一个字符的宽度,经过必定的算法将字符串分割成多个部分,而后分别调用drawText一部分一部分的显示, 可是这种显示效率会很低。
StaticLayout是android中处理文字换行的一个工具类,StaticLayout已经实现了文本绘制换行处理
Activity.onBackPressed() 很方便的管理back键的方法,有时候须要本身控制返回键的事件的时候,能够重写一下。好比加入 “点两下back键退出” 功能。
GestureDetector 用来监听和相应对应的手势事件,好比点击,长按,慢滑动,快滑动,用起来很简单,比你本身实现要方便许多。
ViewStub 它是一个初始化不作任何事情的 View,可是以后能够载入一个布局文件。在慢加载 View 中很适合作占位符。
SystemClock.sleep() 这个方法在保证必定时间的 sleep 时很方便,一般用来进行 debug 和模拟网络延时。
Fragment.setArguments,由于在构建 Fragment 的时候不建议加参数,因此这是个很好的东西,能够在建立 Fragment 以前设置参数
DialogFragment.setShowsDialog () 这是一个很巧妙的方式,DialogFragment 能够做为Dialog显示。
LocalBroadcastManager 这个会比全局的 broadcast 更加安全,简单,快速。一个简单的应用就是退出程序。
public class BaseApplication extends Application {
public final static String ACTION_EXIT_APP = "package.exit";
private static LocalBroadcastManager mLocalBroadcatManager;
private static Context mContext;
private static BaseApplication instance;
public static Context getContext() {
return mContext;
}
/**
* 得到LocalBroadcastManager对象 * @return LocalBroadcastManager对象
*/
public static LocalBroadcastManager getLocalBroadcastManager() {
if (mLocalBroadcatManager == null) {
mLocalBroadcatManager = LocalBroadcastManager.getInstance(mContext);
}
return mLocalBroadcatManager;
}
@Override
public void onCreate() {
super.onCreate();
instance = this;
mContext = this.getApplicationContext();
CorePageManager.getInstance().init(this);
}
/**
* 发送本地广播退出程序
*/
public void exitApp() {
Intent intent = new Intent();
intent.setAction(ACTION_EXIT_APP);
intent.addCategory(Intent.CATEGORY_DEFAULT);
BaseApplication.getLocalBroadcastManager().sendBroadcast(intent);
BaseActivity.unInit();
}
}
public class BaseActivity extends FragmentActivity {
public final static String ACTION_EXIT_APP = "package.exit";
/** * 仅用于接受应用退出广播,程序退出时有机会作一些必要的清理工做 */
private BroadcastReceiver mExitReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{ String action = intent.getAction();
if (action.equals(ACTION_EXIT_APP)) {
Log.d(TAG,"exit from broadcast"); finish();
}
}
};
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
IntentFilter filter = new IntentFilter();
filter.addAction(Config.ACTION_EXIT_APP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
BaseApplication.getLocalBroadcastManager().registerReceiver(mExitReceiver, filter); //注册本地广播,接收程序退出广播
}
}
Application.registerActivityLifecycleCallbacks 就是注册 Activity 的生命周期的一些回调方法,就是一个方便的工具
Application经过此接口提供了一套回调方法,用于让开发者对Activity的生命周期事件进行集中处理。
以往若需监测Activity的生命周期事件代码,你多是这样作的,重写每个Acivity的onResume(),而后做统计和处理。
@Override
protected void onResume() {
super.onResume(); //TODO 处理和统计代码
Log.v(TAG, "onResume");
Logger.v(TAG, "onResume");
Logging.v(TAG, "onResume");
...
}
ActivityLifecycleCallbacks接口回调能够简化这一繁琐过程,在一个类中做统一处理
android.app.Application.ActivityLifecycleCallbacks 它要求API 14+ (Android 4.0+),在咱们自定义的Application注册回调。
public void onCreate() {
super.onCreate();
this.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityStopped(Activity activity) {
Logger.v(activity, "onActivityStopped");
}
@Override
public void onActivityStarted(Activity activity) {
Logger.v(activity, "onActivityStarted");
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
Logger.v(activity, "onActivitySaveInstanceState");
}
@Override
public void onActivityResumed(Activity activity) {
Logger.v(activity, "onActivityResumed");
}
@Override
public void onActivityPaused(Activity activity) {
Logger.v(activity, "onActivityPaused");
}
@Override
public void onActivityDestroyed(Activity activity) {
Logger.v(activity, "onActivityDestroyed");
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Logger.v(activity, "onActivityCreated");
}
});
};
这里只是使用Log日志工具做简要测试,如需知足较复杂的统计或调试需求时,此法可能会大大减小插入代码量,提升效率,更多详情请看这个项目AndroidLifecyle
versionNameSuffix这个 gradle 设置可让你在基于不一样构建类型的 manifest 中修改版本名这个属性,例如,若是须要在在 debug 版本中以”-SNAPSHOT”结尾,那么就能够轻松的看出当前是 debug 版仍是 release 版。
buildTypes { release { versionNameSuffix "sample" } }
-nodpi 在没有特别定义的状况下,不少修饰符(-mdpi,-hdpi,-xdpi等等)都会默认自动缩放 assets/dimensions,有时候咱们须要保持显示一致,这种状况下就可使用 -nodpi。
Activity.recreate () 强制让 Activity 重建
BroadcastRecevier.setDebugUnregister ()什么用不知道,调试用的。
android:weightSum (LinearLayout)这个颇有用,在百分比布局没有出来前,基本上就是经过这个属性以及layout_weight属性来间接达到百分比。
android:duplicateParentState (View) 此方法可使得子 View 能够复制父 View 的状态。好比若是一个 ViewGroup 是可点击的,那么能够用这个方法在它被点击的时候让它的子 View 都改变状态。
android:tileMode (BitmapDrawable)能够指定图片使用重复填充的模式。
android:enterFadeDuration/android:exitFadeDuration (Drawables)此属性在 Drawable 具备多种状态的时候,能够定义它展现前的淡入淡出效果。
android:scaleType (ImageView)定义在 ImageView 中怎么缩放/剪裁图片,通常用的比较多的是centerCrop和centerInside。
Merge此标签能够在另外一个布局文件中包含别的布局文件,而不用再新建一个 ViewGroup,对于自定义 ViewGroup 的时候也须要用到;能够经过载入一个带有标签的布局文件来自动定义它的子部件。
AtomicFile经过使用备份文件进行文件的原子化操做的类
ViewDragHelper视图拖动是一个比较复杂的问题。这个类能够帮助解决很多问题。能够参考这篇文章Android ViewDragHelper彻底解析 自定义ViewGroup神器
**PopupWindow**Android处处都在使用PopupWindow ,甚至你都没有意识到(标题导航条ActionBar,自动补全AutoComplete,编辑框错误提醒Edittext Errors)。这个类是建立浮层内容的主要方法。
**SparseArray**Map的高效优化版本。推荐了解姐妹类SparseBooleanArray、SparseIntArray和SparseLongArray。在编写通用适配器的时候SparseArray可能会用到
PackageManager.setComponentEnabledSetting()能够用来启动或者禁用程序清单中的组件。对于关闭不须要的功能组件是很是赞的,好比关掉一个当前不用的广播接收器。
SQLitedatabase.yieldIfContendedSafely()让你暂时中止一个数据库事务, 这样你能够就不会占用太多的系统资源。
Environment.getExternalStoragePublicDirectory()仍是那句话,用户指望在SD卡上获得统一的用户体验。用这个方法能够得到在用户设备上放置指定类型文件(音乐、图片等)的正确目录。
Context.getExternalFilesDir()申请了SD卡写权限后,你能够在SD的任何地方写数据,把你的数据写在设计好的合适位置会更加有礼貌。这样数据能够及时被清理,也会有更好的用户体验。此外,Android 4.0 Kitkat中在这个文件夹下写数据是不须要权限的,每一个用户有本身的独立的数据存储路径。该API从V8才开始支持。
View.generateViewId()每次我都想要推荐动态生成控件的ID。须要注意的是,不要和已经存在的控件ID或者其余已经生成的控件ID重复。
ActivityManager.clearApplicationUserData() 一键清理你的app产生的用户数据,多是作用户退出登陆功能,有史以来最简单的方式了。之前本身的作法真是不忍直视啊。
ActivityOptions方便的定义两个Activity切换的动画。 使用ActivityOptionsCompat 能够很好解决旧版本的兼容问题。使用ActivityOptionsCompat 类能够很方便的实现Material Design的切换动画
ViewParent.requestDisallowInterceptTouchEvent() Android系统触摸事件机制大多时候可以默认处理,不过有时候你须要使用这个方法来剥夺父级控件的控制权。
Fragment 的 setUserVisibleHint方法,可实现 fragment 对用户可见时才加载资源(延迟加载)
IntentService一个能够干完活后本身去死且不须要咱们去管理子线程的Service
Executors. newSingleThreadExecutor()单线程顺序执行的任务队列
**android:animateLayoutChanges=”true”**LinearLayout中添加View的动画的办法,支持经过setLayoutTransition()自定义动画
GradientDrawable渐变,可实现阴影效果
PointF,graphics包中的一个类,咱们常常见到在处理Touch事件的时候分别定义一个downX,一个downY用来存储一个坐标,若是坐标少还好,若是要记录的坐标过多那代码就很差看了。用PointF(float x, float y);来描述一个坐标点会清楚不少。
StateListDrawable,定义Selector一般的办法都是xml文件,可是有的时候咱们的图片资源多是从服务器动态获取的,好比不少app所谓的皮肤,这种时候就只能通StateListDrawable来完成了,各类addState便可。
includeFontPadding=”false”,TextView默认上下是有必定的padding的,有时候咱们可能不须要上下这部分留白,加上它便可。
onTrimMemory,在Activity中重写此方法,会在内存紧张的时候回调(支持多个级别),便于咱们主动的进行资源释放,避免OOM。
Fragment在onAttach方法中接收回调
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mPageSelectedListener = (PageSelectedListener) activity;
mMenuBtnOnclickListener = (MenuBtnOnClickListener) activity;
mCommitBtnOnClickListener = (CommitBtnOnClickListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + "must implements listener");
}
}
经过 WindowManager.addView 在其余app界面添加一个view时,常常会没法显示,特别在miui,emui固件上,须要指定type为LayoutParams.TYPE_TOAST。
Paint.setXfermode(porterDuffXfermode),在ApiDemo里面有专门的介绍,实现了穿透,叠加,覆盖等多种绘制效果,很是实用。在自定义View中用的比较多。
经过View.getDrawingCache()能够获取截图,可是须要setDrawingCacheEnabled(true)频繁使用可能会oom,还有一种方法直接用canvas
Bitmap bm = Bitmap.createBitmap((int) (w * scale), (int) (h*scale), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas();
canvas.setBitmap(bm);
View.draw(canvas);
return bm;
因为fragment的缓存机制决定的。默认状况下,viewpager切换页面时会缓存上一个页面,非相邻页面被销毁,可使用viewPaper.setOffscreenPageLimit()函数来解决
fragment嵌套时,内部fragment的manager经过getChildFragmentManager()得到
布局中,view.bringTofont(),把该view在层叠布局中置于最前面。通样的viewgroup的bringChildtoFont(),都是同样的效果。