zoukankan      html  css  js  c++  java
  • 多个Fragment界面重叠和拍照闪退问题

    记录最近遇到的多个Fragment界面重叠和调用系统相机拍照闪退问题,同时总结解决方案。

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------

     环境:Activity(一个)+Fragment(多个)

    问题一:多个fragment出现重叠现象

    首先,Android管理Fragment有两种方式,使用add、hide、show的方式和replace方式,两种方式各有优缺点。

    --> replace方式
    如果使用这种方式,是可以避免重叠的问题,但是每次replace会把生命周期全部执行一遍,如果在这些生命周期函数里拉取数据的话,就会不断重复的加载刷新数据,所以我们并不推荐使用这种方式。

    --> add、hide、show的方式
    虽然这种方式避免了可能重复加载刷新数据的问题,但是会出现重叠的问题。

    原因:

    当系统内存不足,Fragment 的宿主 Activity 回收的时候,Fragment 的实例并没有随之被回收。Activity 被系统回收时,会主动调用 onSaveInstance() 方法来保存视图层(View Hierarchy),所以当 Activity 通过导航再次被重建时,之前被实例化过的 Fragment 依然会出现在 Activity 中,此时的 FragmentTransaction 中的相当于又再次 add 了 fragment 进去的,hide()和show()方法对之前保存的fragment已经失效了,所以就出现了重叠。
    然而我们还是推荐使用这个,我们可以解决。

    解决方法:MainActivity.Class中重写onAttachFragment,重新让新的Fragment指向了原本未被销毁的fragment,它就是onAttach方法对应的Fragment对象

     @Override
        public void onAttachFragment(Fragment fragment) {
            if (tab1 == null && fragment instanceof Tab1Fragment)
                tab1 = fragment;
            if (tab2 == null && fragment instanceof Tab2Fragment)
                tab2 = fragment;
            if (tab3 == null && fragment instanceof Tab3Fragment)
                tab3 = fragment;
            if (tab4 == null && fragment instanceof Tab4Fragment)
                tab4 = fragment;
        }

    问题二:调用系统相机拍照闪退

    在onActivityResult方法里通过Intent的getData方法获取的数据转换成bitmap并显示在界面上,有时候会有取不到数据,或者显示的bitmap会非常小,如果将bitmap保存到sd卡后会发现,图片的分辨率很低,并且图片大小也是经过压缩的,不管将相机的像素设置多高,最后通过这种方式返回的bitmap总是经过压缩了的。如果想获得理想的照片大小和分辨率改如何处理呢?以下是我的处理方法,虽然不是最好,但是帮我解决了这个需求。我先来简述一下为什么返回的图片是经过了压缩的。 

    大家都知道,现在手机像素少则500W或800W,多则4KW(某亚),就拿常见的800W像素的相机拍出来的照片来说,分辨率大概在3200*2400左右,我的测试机型是LG optimus 2x,2.3.7的系统,用800W像素拍出来大概就是这个分辨率,照片大小在2M左右。试想一下,在Android系统中最常用的Bitmap格式(ARGB_8888)一个像素占用4byte(字节),例如一张分辨率为3200*2400px的照片,其耗用内存情况是:3200*2400*4/1024/1024=29.296875(MB)如果为了一张图片,耗用这么大的内存,肯定是不合理的,并且,官方文档中有说明,Android系统分配给每个应用的最大内存是16M,所以,系统为了防止应用内存占用过大,对于在应用内通过相机拍摄的图片最终返回来的结果进行了压缩,压缩后的图片变得很小,通过之前说的getData的方式只能满足比如显示个头像这样的需求,如果要显示大图,就会出现模糊的情况。如何获得清晰的大图,思路如下:

    1.拍照时,将拍得的照片先保存在本地,其中启动相机程序如下;

            Intent getImageByCameraIntent = new Intent("android.media.action.IMAGE_CAPTURE");       
            Uri imageUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "image.jpg"));
            getImageByCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
           startActivityForResult(getImageByCameraIntent, TAKE_PHOTO);

    2.在onActivityResult方法中再将图片取出,并经过缩小处理再显示在界面上或保存在自定义文件夹下,其中压缩比例自定义;

       @Override  
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                switch (requestCode) {
                case TAKE_PICTURE:
    
              //将保存在本地的图片取出并缩小后显示在界面上
                        Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/image.jpg");
                        Bitmap newBitmap = ImageTools.zoomBitmap(bitmap, bitmap.getWidth() / SCALE, bitmap.getHeight() / SCALE);
                        //由于Bitmap内存占用较大,这里需要回收内存,否则会报out of memory异常
                        bitmap.recycle();
    
                        //将处理过的图片显示在界面上,并保存到本地
                        //取当前时间为照片名
                       String imageName= DateFormat.format("yyyyMMdd_hhmmss",Calendar.getInstance(Locale.CHINA))+".png";
                       ImageTools.savePhotoToSDCard(newBitmap, getPhotoPath(), imageName);
              break;
                default:
                    break;
                }
            }
        }

    其中ImageTools是自定义的图片工具类,zoomBitmap()savePhotoToSDCard()方法具体如下: 

    /**
    * Resize the bitmap
    * 
    * @param bitmap
    * @param width
    * @param height
    * @return
    */
    public static Bitmap zoomBitmap(Bitmap bitmap, int width, int height) {
            int w = bitmap.getWidth();
            int h = bitmap.getHeight();
            Matrix matrix = new Matrix();
            float scaleWidth = ((float) width / w);
            float scaleHeight = ((float) height / h);
            matrix.postScale(scaleWidth, scaleHeight);
            Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
            return newbmp;
        }
    
        /**
         * Save image to the SD card 
         * @param photoBitmap
         * @param photoName
         * @param path
         */
        public static void savePhotoToSDCard(Bitmap photoBitmap,String path,String photoName){
            if (checkSDCardAvailable()) {
                File dir = new File(path);
                if (!dir.exists()){
                    dir.mkdirs();
                }
                
                File photoFile = new File(path , photoName );
                FileOutputStream fileOutputStream = null;
                try {
                    fileOutputStream = new FileOutputStream(photoFile);
                    if (photoBitmap != null) {
                        if (photoBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)) {
                            fileOutputStream.flush();
                        }
                    }
                } catch (FileNotFoundException e) {
                    photoFile.delete();
                    e.printStackTrace();
                } catch (IOException e) {
                    photoFile.delete();
                    e.printStackTrace();
                } finally{
                    try {
                        fileOutputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } 
        } 

     说明:由于Android给bitmap分配的内存最大不超过8M,所以对使用完的较大的Bitmap要释放内存,调用其recycle()方法即可。然后将缩小(缩小方法在Demo源码中有)后的bitmap显示在界面上或保存到SD卡,至于之前保存的原图,可以删掉,也可以放在那,下次拍照时,这张原图就会被下一张照片覆盖,所以SD卡上使用只有一张临时图片,占用也不是很大。

     ---------------------------------------------------------------------------------------------------------------------------------

    参考资料:

    http://blog.csdn.net/whitley_gong/article/details/51987911    //关于Fragment重叠问题分析和解决

    https://m.th7.cn/show/14/201612/1045726.html        //android系统相机的使用、及解决拍照闪退的问题

    http://m.blog.csdn.net/article/details?id=8654137   //Android相机、相册获取图片显示并保存到SD卡

  • 相关阅读:
    python笔记——调试和异常处理
    [算法学习] 线段树,树状数组,数堆,笛卡尔树
    【cpp】G++中不支持static_cast?
    【生活感想】不够淡定
    数值线性代数小结
    伪逆
    统计机器学习
    Numerical Methods with MATLAB(1)
    吐槽iOS国际化:关于NSLocalizedString的使用
    iOS 沙盒路径操作:新建/删除文件和文件夹
  • 原文地址:https://www.cnblogs.com/gis-laozhang/p/6820265.html
Copyright © 2011-2022 走看看