欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

相册幻灯片实现以及Activity白屏问题解决

程序员文章站 2022-05-26 19:55:57
...

将相册(自己写,非原生相册)从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)

相册幻灯片实现以及Activity白屏问题解决


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!