1、对文件进行读写枷锁,使用了nio技术
RandomAccessFile randomFile = null; byte[] buf = new byte[1024]; int count = 0; try { randomFile = new RandomAccessFile(new File(filePath), "rws"); FileChannel channel = randomFile.getChannel(); while ((count = is.read(buf)) > 0) { FileLock lock = channel.tryLock(); randomFile.write(buf, 0, count); lock.release(); } return BitmapFactory.decodeFile(filePath); } catch (IOException e) { e.printStackTrace(); return null; } finally { if (randomFile != null) try { randomFile.close(); } catch (IOException e) { e.printStackTrace(); } closeStream(is, null); }
2、当页面中需要横向滑动和纵向滑动时的时间判断机制:重写父view
public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = ev.getAction();//获取触摸事件类型 final float x = ev.getX();//每次触摸事件的x坐标 final float y = ev.getY();//每次触摸事件的y坐标 switch (action) { case MotionEvent.ACTION_DOWN://按下事件 mLastMotionX = x;//初始化每次触摸事件的x方向的初始坐标,即手指按下的x方向坐标 mLastMotionY = y;//初始化每次触摸事件的y方向的初始坐标,即手指按下的y方向坐标 break; case MotionEvent.ACTION_MOVE: final intdeltaX = (int) (mLastMotionX - x);//每次滑动事件x方向坐标与触摸事件x方向初始坐标的距离 final intdeltaY = (int) (mLastMotionY - y);//每次滑动事件y方向坐标与触摸事件y方向初始坐标的距离 boolean xMoved = Math.abs(deltaX) > mTouchSlop && Math.abs(deltaY/deltaX) < 1; //判断触摸事件处理的传递方向,该业务中是, //x方向的距离大于手指,并且y方向滑动的距离小于x方向的滑动距离时,Gallery消费掉此次触摸事件 //如果需要,请在您的业务中,改变判断的逻辑 if (xMoved) {//Gallery需要消费掉此次触摸事件 return true;//返回true就不会将此次触摸事件传递给子View了,我的业务中是ListView } break; } return false;//将此次触摸事件传递给子View,即ListView }
3、手机内存信息查看注释:
VSS - Virtual Set Size 虚拟耗用内存(包含共享库占用的内存) RSS - Resident Set Size 实际使用物理内存(包含共享库占用的内存) PSS - Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存) USS - Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)
4、查看单个应用内存使用情况命令:
查看单个应用程序内存占用量的命令:adb shell dumpsys meminfo [包名]|[进程号]
5、外置SD卡和手机内置内存:
public static File getDiskCacheDir(Context context, String uniqueName) { // 先检查外部存储是否挂载,如果挂载了,则使用外存,否则使用内存路径 final String cachePath = Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || isExternalStorageRemovable() ? getExternalCacheDir(context).getPath() : context.getCacheDir() .getPath(); return new File(cachePath + File.separator + uniqueName); }
6、查看网络连接是否可用:
final ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); final NetworkInfo networkInfo = cm.getActiveNetworkInfo(); if(networkInfo == null || !networkInfo.isConnectedOrConnecting()){ //提示用户设置网络: Toast.makeText(context, R.string.no_network_connection_toast , Toast.LENGTH_SHORT).show(); Log.e(TAG, "checkConnection - no connection found"); }
7、获取目前该手机能显示指定宽度图片多少列:
mImageThumbSize = getResources().getDimensionPixelSize(R.dimen.image_thumbnail_size); mImageThumbSpacing = getResources().getDimensionPixelSize(R.dimen.image_thumbnail_spacing); int numColumns = (int) Math.floor(mGridView.getWidth() / (mImageThumbSize + mImageThumbSpacing)); //Adapter中这样设置: public int getCount() { // Size + number of columns for top empty row return Images.imageThumbUrls.length + mNumColumns; } public Object getItem(int position) { return position < mNumColumns ? null : Images.imageThumbUrls[position - mNumColumns]; } public long getItemId(int position) { return position < mNumColumns ? 0 : position - mNumColumns; }
8、图片下载缓存类使用方法:
先设置imageCacheParams new ImageCacheParams(getActivity(), IMAGE_CACHE_DIR); cacheParams.setMemCacheSizePercent(0.25f); // Set memory cache to 25% of app memory 创建一个mImageFetcher 设置下载完成之前要显示的图片 添加到缓存 addImageCache(); 对ListView的滑动状态进行监听 onScrollStateChange(){ if(scrollState == .SCROLL_STATE_FLING{ mImageFetcher.setPauseWork(true); }else{ mImageFetcher.setPauseWork(false); } } 然后 onResume mImageFetcher.setExitTasksEarly(false); onPause mImageFetcher.setExitTasksEarly(true); onDestory() mImageFetcher.colseCache(); mImageFetcher.setImageSize(height); 使用的时候: mImageFetcher.loadImage(Images.imageThumbUrls[position - mNumColumns], imageView); int numColumns = (int) Math.floor( mGridView.getWidth() / (mImageThumbSize + mImageThumbSpacing));
9、获取当前手机的宽高:
DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); final int height = displayMetrics.heightPixels; final int width = displayMetrics.widthPixels;
10、为了避免图片被重复下载,需要缓存图片。我可以通过获取头信息来保证我们的图片不过期(有效的缓存动态数据):
long currentTime = System.currentTimeMillis()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); long expires = conn.getHeaderFieldDate("Expires", currentTime); long lastModified = conn.getHeaderFieldDate("Last-Modified", currentTime); setDataExpirationDate(expires); if (lastModified < lastUpdateTime) { // Skip update } else { // Parse update }11、获取Android系统app的缓存路径:
//外部缓存,用来缓存不敏感的数据,在Froyo之后 Context.getExternalCacheDir(); //内部缓存,是安全的应用程序缓存,但是当系统低可用存储的是该部分可能被刷新 Context.getCache(); //不论你将数据存储在那种缓存中,当应用程序卸载后该数据都将被清除。 /** * Get the external app cache directory. * * @param context The context to use * @return The external cache dir */ @TargetApi(8) public static File getExternalCacheDir(Context context) { if (Utils.hasFroyo()) { return context.getExternalCacheDir(); } // Before Froyo we need to construct the external cache dir ourselves final String cacheDir = "/Android/data/" + context.getPackageName() + "/cache/"; return new File(Environment.getExternalStorageDirectory().getPath() + cacheDir); }12、关于HttpURLConnection Response Cache:在Android 4.0中添加了HttpURLConnection响应的缓存,你可以用HTTP响应,在支持设备上使用反射缓存数据:
private void enableHttpResponseCache() { try { long httpCacheSize = 10 * 1024 * 1024; // 10 MiB File httpCacheDir = new File(getCacheDir(), "http"); Class.forName("android.net.http.HttpResponseCache") .getMethod("install", File.class, long.class) .invoke(null, httpCacheDir, httpCacheSize); } catch (Exception httpResponseCacheNotAvailable) { Log.d(TAG, "HTTP response cache is unavailable."); } }上面的这段代码在4.0以上设备中将打开response cache,并且不影响其他低版本
|
|
/** * Check how much usable space is available at a given path. * * @param path The path to check * @return The space available in bytes */ @TargetApi(9) public static long getUsableSpace(File path) { if (Utils.hasGingerbread()) { return path.getUsableSpace(); } final StatFs stats = new StatFs(path.getPath()); return (long) stats.getBlockSize() * (long) stats.getAvailableBlocks(); }14、标准下载实例:
/** * Download something from a URL and write the content to an output stream. * * @param urlString The URL to fetch * @return true if successful, false otherwise */ public boolean downloadUrlToStream(String urlString, OutputStream outputStream) { disableConnectionReuseIfNecessary(); HttpURLConnection urlConnection = null; BufferedOutputStream out = null; BufferedInputStream in = null; try { final URL url = new URL(urlString); urlConnection = (HttpURLConnection) url.openConnection(); in = new BufferedInputStream(urlConnection.getInputStream(), IO_BUFFER_SIZE); out = new BufferedOutputStream(outputStream, IO_BUFFER_SIZE); int b; while ((b = in.read()) != -1) { out.write(b); } return true; } catch (final IOException e) { Log.e(TAG, "Error in download- " + e); } finally { if (urlConnection != null) { urlConnection.disconnect(); } try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (final IOException e) {} } return false; } /** * Workaround for bug pre-Froyo, see here for more info: * http://android-developers.blogspot.com/2011/09/androids-http-clients.html */ public static void disableConnectionReuseIfNecessary() { // HTTP connection reuse which was buggy pre-froyo if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { System.setProperty("http.keepAlive", "false"); } }15、Android屏幕解锁和点亮:
KeyguardManager km= (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); //得到键盘锁管理器对象 KeyguardLock kl = km.newKeyguardLock("unLock"); //参数是LogCat里用的Tag kl.disableKeyguard(); //解锁 PowerManager pm=(PowerManager) getSystemService(Context.POWER_SERVICE);//获取电源管理器对象 PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK, "bright"); //获取PowerManager.WakeLock对象,后面的参数|表示同时传入两个值,最后的是LogCat里用的Tag wl.acquire();//点亮屏幕 wl.release();//释放 //需要的权限: <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />16、查看android每帧的绘制时间:
$ adb shell dumpsys gfxinfo packagename
将标记为Profile的毫秒级的数据,这段数据包含了一个有三列数据的表,应用的每个window都有一个这样的表,为了使用这个数据,你可以简单的讲这个表拷贝到你喜欢的电子制表软件中,从而生成一个数据堆叠的列图。每一列给出了每一帧花在渲染上的时间估计:
“Draw”是指Java层用在创建“display lists”(显示列表)上的时间。它表明运行例如View.onDraw(Canvas)需要多少时间。
“Process”是指Android 2D渲染引擎用在执行“display lists”上的时间。你的UI层级(hierarchy)中的View数量越多,需要执行的绘画命令就越多。
“Execute”是指将一帧图像交给合成器(compositor)的时间。这部分占用的时间通常比较少以60fps的帧率进行平滑的渲染,每一帧所占用的时间需要要少于16ms
17、也可以使用Systrace来检查问题,setting->developer options->Enable traces->在dialog中选择要监视的项目,比如Graphics、View。不要忘记关闭profile GPU rendering。然后在tools/systrace目录下,运行$./sysytrace.py这个工具默认会记录5秒内发生的事情。可以看到一个用HTML文档展现结果。
18、开启GPU视图更新之后,色块代表的意思:
如果你记得每种颜色所表示的含义,你就能很容易的知道结果是什么:
没有颜色就表示没有重绘。每个像素只画了一次。在这个例子里,你可以看到背景是完全无色的。
蓝色:表示重绘了一次。每个像素只画了两次。大块的蓝色是可以接受的。(如果整个window是蓝色的,你就可以使用一个图层(layer)。)
绿色:表示重绘了两次。每个像素画了三次。中等尺寸的绿色方块是可以接受的,但你最好尝试做出优化。
红色:表示重绘了三次。这个像素被画了四次。很小尺寸的红色方块是可以接受的。
黑色:表示重绘了四次及以上。这个像素被画了五次及以上。这个是错的,需要解决。
基于这些信息,你可以看到“设置”应用表现地很好,不需要额外的改进。只有在切换时有一点点红块,但不需要我们再做什么工作了。
19、当作为第三方包时,检查当前应用是否包含某权限(访问网络的权限):
Context.checkCallingOrSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED