将相册(自己写,非原生相册)从Android4.4移植到Android6.0上,出现了播放幻灯片,第一张为白屏,后续进入正常的情况

相同的代码,不一样的效果。

首先,我先将幻灯片页面粘出来,并添加注释。

涉及的知识点:BitmapUtils、ViewFlipper


BitmapUtils

// 初始化xutils中的加载图片的工具
mBitmapUtils = new BitmapUtils(this);

// 设置默认加载图片
mBitmapUtils.configDefaultLoadingImage(R.drawable.slide_default);

public View addImageById(String path) {
        ImageView iv = new ImageView(this);
// 获取图片路径, 使用路径下载图片, 将图片设置给ImageView, 考虑内存溢出问题, 图片本地缓存
        mBitmapUtils.display(iv, path);
        return iv;
    }



ViewFlipper

private void initView() {
//给组件设置动画
mViewFlipper = (ViewFlipper) findViewById(R.id.imageFlipper); 
mViewFlipper.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in)); 
mViewFlipper.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out)); }
//显示下一个组件
mViewFlipper.showNext();
//动态加载
ViewmViewFlipper.addView(addImageById(path));



幻灯片播放页面


public class SlideShowActivity extends Activity implements OnGestureListener {
    private static final String TAG = "SlideShowActivity";
    public static final String CURRENT_POSITION = "currentPosition";
    public static final String ACTION_STOP_SLIDESHOW = "com.avatar.album.stop_slideshow";

    private static final int DELAYTIME = 3000;
    private static final int SHOWTIME = 3000;
    private static final int MSG_HIDECONTROLUI = 1;
    private static final int MSG_STOP = 2;
    private static final int MSG_SHOW = 3;
    public static SlideShowActivity instance = null;

    private final List<File> mPicList = new ArrayList<File>();
    private ImageView mClose;
    private ImageView mPause;
    private ImageView mResume;
    private RelativeLayout mTopBar;
    private RelativeLayout mBottomBar;
    private boolean mIsControlUI = true;
    private ViewFlipper mViewFlipper;
    private BitmapUtils mBitmapUtils;
    private ContentResolver mResolver;
    private int mCurrentPosition;
    private int mCount;

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                //点击屏幕UI的变化
                case MSG_HIDECONTROLUI:
                    if (!mIsControlUI) {
                        mTopBar.setVisibility(View.GONE);
                        mBottomBar.setVisibility(View.GONE);
                        mIsControlUI = true;
                    }
                    break;
                //播放停止
                case MSG_STOP:
                    setSlideShowResult();
                    finish();
                    break;
                //播放过程
                case MSG_SHOW:
                    if (mCount >= 0) {
                        mViewFlipper.showNext();
                        mHandler.sendEmptyMessageDelayed(MSG_SHOW, SHOWTIME);
                        mCount--;
                        mCurrentPosition--;
                    } else {
                        Intent intent = new Intent();
                        intent.putExtra(CURRENT_POSITION, -1);
                        setResult(Activity.RESULT_OK, intent);
                        finish();
                    }
                    break;

                default:
                    break;
            }
        }
    };

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            //这个广播为通过相册主页面停止幻灯片的播放
            if (intent.getAction().equals(
                    HomeFragmentActivity.ACTION_STOP_SLIDE)) {
                mHandler.sendEmptyMessage(MSG_STOP);
            }
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.slide_show_photo);
        mResolver = this.getContentResolver();

        mClose = (ImageView) findViewById(R.id.img_back);
        mPause = (ImageView) findViewById(R.id.img_pause);
        mResume = (ImageView) findViewById(R.id.img_resume);
        mTopBar = (RelativeLayout) findViewById(R.id.top_bar);
        mBottomBar = (RelativeLayout) findViewById(R.id.bottom_bar);
        mClose.setOnClickListener(clickListener);
        mPause.setOnClickListener(clickListener);
        mResume.setOnClickListener(clickListener);
        mTopBar.setVisibility(View.GONE);
        mBottomBar.setVisibility(View.GONE);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(HomeFragmentActivity.ACTION_STOP_SLIDE);
        registerReceiver(mBroadcastReceiver, intentFilter);
        
        mBitmapUtils = new BitmapUtils(this);
        
        //加载幻灯片的初始话
        mBitmapUtils.configDefaultLoadingImage(R.drawable.slide_default);
        
        //添加动画
        initView();
        
        //获取展示相片页面当前的照片位置
        mCurrentPosition = getIntent().getIntExtra("currentPosition",
                mPicList.size() - 1);
        Log.i(TAG, "current position : " + mCurrentPosition);
        instance = this;

        Cursor cursor = null;
        try {
            cursor = mResolver.query(Media.EXTERNAL_CONTENT_URI, null, null,
                    null, null);

            for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
                int dataIndex = cursor.getColumnIndex(Media.DATA);
                String path = cursor.getString(dataIndex).toString();
                Log.i(TAG, "path " + path);

                if (path != null) {
                    String type = path.substring(path.lastIndexOf("/") + 1);
                    if (type.contains("jpg")) {
                        File file = new File(path);
                        mPicList.add(file);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        for (int i = mCurrentPosition; i >= 0; i--) {
            String path = mPicList.get(i).toString();
            mViewFlipper.addView(addImageById(path));
        }

        for (int i = mPicList.size() - 1; i > mCurrentPosition; i--) {
            String path = mPicList.get(i).toString();
            mViewFlipper.addView(addImageById(path));
        }

        mCount = mPicList.size() - 1;
        mHandler.sendEmptyMessageDelayed(MSG_SHOW, SHOWTIME);
        mCount--;
        mCurrentPosition--;
    }

    @Override
    protected void onResume() {
        super.onResume();
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mPause.performClick();
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        instance = null;
        unregisterReceiver(mBroadcastReceiver);
    }

    private final OnClickListener clickListener = new OnClickListener() {
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.img_back:
                    mHandler.sendEmptyMessage(MSG_STOP);
                    break;
                    
                //暂停幻灯片的播放
                case R.id.img_pause:
                    mHandler.removeMessages(MSG_SHOW);
                    mPause.setVisibility(View.GONE);
                    mResume.setVisibility(View.VISIBLE);
                    break;
                
                //继续幻灯片的播放
                case R.id.img_resume:
                    mHandler.sendEmptyMessageDelayed(MSG_SHOW, SHOWTIME);
                    mPause.setVisibility(View.VISIBLE);
                    mResume.setVisibility(View.GONE);
                    break;
            }
        }
    };

    private void initView() {
        mViewFlipper = (ViewFlipper) findViewById(R.id.imageFlipper);
        mViewFlipper.setInAnimation(AnimationUtils.loadAnimation(this,
                android.R.anim.fade_in));
        mViewFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,
                android.R.anim.fade_out));
    }

    //通过照片的连接链接将其转化为ImageView
    public View addImageById(String path) {
        ImageView iv = new ImageView(this);
        mBitmapUtils.display(iv, path);
        return iv;
    }

    @Override
    public boolean onKeyDown(int keyCode, android.view.KeyEvent event) {
        if (keyCode == android.view.KeyEvent.KEYCODE_BACK) {
            setSlideShowResult();
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        final int action = e.getActionMasked();

        switch (action) {
            case MotionEvent.ACTION_UP:
                if (mIsControlUI) {
                    mTopBar.setVisibility(View.VISIBLE);
                    mBottomBar.setVisibility(View.VISIBLE);
                    mIsControlUI = false;
                    mHandler.removeMessages(MSG_HIDECONTROLUI);
                    mHandler.sendEmptyMessageDelayed(MSG_HIDECONTROLUI, DELAYTIME);
                } else {
                    mTopBar.setVisibility(View.GONE);
                    mBottomBar.setVisibility(View.GONE);
                    mIsControlUI = true;
                }
                break;

            default:
                break;
        }
        return super.onTouchEvent(e);
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
            float distanceY) {
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
        return false;
    }

    //播放完毕,将结果返回照片展示页面
    private void setSlideShowResult() {
        Intent intent = new Intent(ACTION_STOP_SLIDESHOW);

        Log.i(TAG, "mCount" + mCount + " mPicList" + mPicList.size());
        if (-1 <= mCount && mCount < mPicList.size()) {
            if (mCurrentPosition >= -1) {
                mCurrentPosition++;
            } else {
                mCurrentPosition += (mPicList.size() + 1);
            }
            Log.i(TAG, "mHandler.mCount = " + mCount + " mCurrentPosition = "
                    + mCurrentPosition);
            intent.putExtra(CURRENT_POSITION, mCurrentPosition);
        } else {
            intent.putExtra(CURRENT_POSITION, -1);
        }

        sendBroadcast(intent);
    }
}



实现幻灯片页面,发现每次重启系统,点开应用播放幻灯片,第一次都会显示白屏,进儿播放正常的幻灯片,而且4.4上是正常的,6.0出现此问题。

我最先想到的是debug检查BitmapUtils获取默认图片以及加载图片转换Bitmap对象是否耗时


long start = System.currentTimeMillis();
mBitmapUtils = new BitmapUtils(this);
mBitmapUtils.configDefaultLoadingImage(R.drawable.slide_default);
long end = System.currentTimeMillis();
Log.i(TAG, (end-start) + "");



截取Log结果(Linux)


android 相册幻灯片效果 安卓 照片幻灯片_白屏


2毫秒而已...
此刻我的内心是非常崩溃。
排查哪些地方耗时,包括动画,包括查询数据库,这个过程就不多说了。
最后做出优化:
//这里只粘onCreate和优化部分,将所有可能的耗时操作都在子线程做。


public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.slide_show_photo);
        mResolver = this.getContentResolver();

        mClose = (ImageView) findViewById(R.id.img_back);
        mPause = (ImageView) findViewById(R.id.img_pause);
        mResume = (ImageView) findViewById(R.id.img_resume);
        mTopBar = (RelativeLayout) findViewById(R.id.top_bar);
        mBottomBar = (RelativeLayout) findViewById(R.id.bottom_bar);
        mClose.setOnClickListener(clickListener);
        mPause.setOnClickListener(clickListener);
        mResume.setOnClickListener(clickListener);
        mTopBar.setVisibility(View.GONE);
        mBottomBar.setVisibility(View.GONE);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(HomeFragmentActivity.ACTION_STOP_SLIDE);
        registerReceiver(mBroadcastReceiver, intentFilter);

        long start = System.currentTimeMillis();
        initView();
        mBitmapUtils = new BitmapUtils(this);
        initData();
        long end = System.currentTimeMillis();
        Log.i(TAG, (end-start) + "ms");
        mCurrentPosition = getIntent().getIntExtra("currentPosition",
                mPicList.size() - 1);
        Log.i(TAG, "current position : " + mCurrentPosition);
        instance = this;
    }


    private void initData() {
        new Thread() {
            public void run() {
                Cursor cursor = null;
                try {
                    cursor = mResolver.query(Media.EXTERNAL_CONTENT_URI, null, null,
                            null, null);

                    for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
                        int dataIndex = cursor.getColumnIndex(Media.DATA);
                        String path = cursor.getString(dataIndex).toString();
                        Log.i(TAG, "path " + path);

                        if (path != null) {
                            String type = path.substring(path.lastIndexOf("/") + 1);
                            if (type.contains("jpg")) {
                                File file = new File(path);
                                mPicList.add(file);
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (cursor != null) {
                        cursor.close();
                    }
                }

                runOnUiThread(new Runnable() {
                    public void run() {
                        for (int i = mCurrentPosition; i >= 0; i--) {
                            String path = mPicList.get(i).toString();
                            mViewFlipper.addView(addImageById(path));
                        }

                        for (int i = mPicList.size() - 1; i > mCurrentPosition; i--) {
                            String path = mPicList.get(i).toString();
                            mViewFlipper.addView(addImageById(path));
                        }
                    }
                });

                mCount = mPicList.size() - 1;
                mHandler.sendEmptyMessageDelayed(MSG_SHOW, SHOWTIME);
                mCount--;
                mCurrentPosition--;
            };
        }.start();
    }



自信的将代码Push重新编译运行。 呵呵,咖喱给给。

看来并不是耗时的问题

排除耗时,还有的可能就是6.0有很多新特性,每次开机加载都比4.4要多用时间和资源,然后咨询了同组的92年已绝顶的大神,给出以下方案。。

修改Activity主题,将其设置为透明色:


<style name="ActivityTheme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsTranslucent">true</item>
    </style>


给Activity添加主题:


<activity
            android:name="com.avatarmind.album.robot.SlideShowActivity"
            android:launchMode="singleInstance"
            android:screenOrientation="landscape"
            android:theme="@style/ActivityTheme" >
        </activity>



白屏变为透明..

用户每次点击播放幻灯片,不会白屏,只是会短暂的透明,也用不了多少毫秒。

缺点:

这种通过主题来给windows设置透明,幻灯片添加的属性动画消失。



那么不让属性动画消失还有什么方法呢?

给Activity添加一张透明的图片:



<style name="ActivityTheme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@drawable/select_nothing</item>
    </style>

缺点:
这张透明的图片内存无法回收。
所以,推荐大家使用第一种。  Fighting!