Android音乐App开发准备( 简易音乐 二 )

Android音乐App开发准备( 简易音乐 二 )

关于

  第一篇看Android音乐App开发准备( 简易音乐 一 )在写第二篇之前,我遇到了一个bug(死活不进启动页面),几乎没有任何提示。后面经过调试发现原来是在子线程里面忘记添加了mCountDownLatch.countDown();,导致线程一直被阻塞

 ExecutorService pool = Executors.newFixedThreadPool(CORE_POOL_SIZE);
        pool.submit(new Runnable() {
            @Override
            public void run() {
                //吐司初始化
               // ToastUtils.init(instance,new ToastQQStyle(instance));
               // mCountDownLatch.countDown();

            }
        });

        pool.submit(new Runnable() {
            @Override
            public void run() {
               
               

            }
        });
        try {
         
            //如果await之前没有调用countDown那么就会一直阻塞在这里
            mCountDownLatch.await();
        }catch (InterruptedException e){
            e.printStackTrace();
        }

  后面我把注释解开之后,使用了权限申请拒绝之后奔溃了:

  PermissionX.init(this)
                .permissions(ARR_NEED_PERMISSIONS)
                .request((allGranted, grantedList, deniedList) -> {
                    if (allGranted){
                        //开始倒计时
                        startCountDown();
                    }else {
                        ToastUtils.show("缺少如下权限"+deniedList);
                    }
                });

  原因是ToastUtils未初始化,原来是因为我在子线程里面初始化了Toast,可是我是想着优化冷启动的,但是可不想生成bug,后面百度一番,学习了一波,知道了IdleHandler,修改代码如下:

Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
           @Override
           public boolean queueIdle() {
               //空闲时初始化
                ToastUtils.init(instance,new ToastQQStyle(instance));
               return false;
           }
       });

  问题解决,冷启动速度依然优化成功。
补充:
  在后面我又发现程序运行奔溃了,还是提示的toast未初始化,毕竟我之前的IdleHandler只是在空闲的时候初始化,如果程序第一次打开没问题,可是后面拒绝权限申请后再次打开,涉及到其他初始化使用到了message导致暂时不空闲也就未初始化了,所以暂时先放到oncreate里面去初始化。

效果:

在这里插入图片描述

编写Activity基类-BaseActivity

  编写view层基类:

public interface BaseView {
}

  编写Model层基类:

public interface BaseModel {
}

  编写控制层基类:

public class BasePresenter<V extends BaseView, M extends BaseModel> {

    protected V mView;
    protected M mModel;


    public void unSubscribe(){
        if(mView != null){
            mView = null;
        }
    }
}

  编写基类BaseActivity,其中的StatusBarUtil工具类使用教程参考android实现沉浸式状态栏

/**
 * Activity基类
 */
public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity {
    protected Unbinder unbinder;
    protected P mPresenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (onCreatePresenter() != null) {
            mPresenter = onCreatePresenter();
        }


    }

    @Override
    public void setContentView(int layoutResID) {
        super.setContentView(layoutResID);
        injectView();
        initModule();
        initData();
    }

    private void injectView() {
        unbinder = ButterKnife.bind(this);
        StatusBarUtil.setColor(this,getResources().getColor(R.color.colorAccent),0);

    }
    @Override
    protected void onResume() {
        super.onResume();

    }
    public void setBackBtn() {
        ImageView backBtn = findViewById(R.id.iv_back);
        backBtn.setVisibility(View.VISIBLE);
      /*  VectorDrawableCompat vectorDrawableCompat = VectorDrawableCompat.create(getResources(), R.drawable.shape_back, getTheme());
        //你需要改变的颜色
        vectorDrawableCompat.setTint(Color.parseColor(color));*/
     //  backBtn.setImageDrawable(vectorDrawableCompat);
        backBtn.setOnClickListener(v -> {
            System.gc();
            onBackPressed();
        });
    }

    protected abstract P onCreatePresenter();
    protected abstract void initData();
    protected abstract void initModule();
    @Override
    protected void onPause() {
        super.onPause();

    }
    @Override
    protected void onDestroy() {
        System.gc();
        if (mPresenter != null) {
            mPresenter = null;
        }
        super.onDestroy();



    }

    /**
     * 页面跳转
     *
     * @param cls
     */
    public void  startActivity(Class<?> cls){
          startActivity(cls,null);
    }

    /**
     * 携带数据的页面跳转
     *
     * @param cls
     * @param bundle
     */
    public void startActivity(Class<?> cls,Bundle bundle){
        Intent intent = new Intent(this,cls);
        if (bundle != null){
            intent.putExtras(bundle);
        }
        startActivity(intent);
    }

    /**
     * 要求有返回值
     *
     * @param cls
     * @param bundle
     * @param requestCode
     */
    public void startActivityForResult(Class<?> cls, Bundle bundle,
                                       int requestCode) {
        Intent intent = new Intent();
        intent.setClass(this, cls);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivityForResult(intent, requestCode);
    }

}

  新建文件夹login,新增SplashActivity页面,项目结构图如下:
在这里插入图片描述

  修改styles.xml文件,修改默认AppTheme样式,新增启动页(SplashActivity)样式:

 <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowIsTranslucent">true</item>
        <!--Android 5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色-->
        <item name="android:statusBarColor" tools:ignore="NewApi">#00000000</item>
    </style>
    <!--启动页样式-->
    <style name="ThemeSplash" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowTranslucentNavigation" tools:ignore="NewApi">true</item>
        <!--解决部分手机隐藏状态栏顶部出现小黑条的问题-->
        <item name="android:windowLayoutInDisplayCutoutMode" tools:ignore="NewApi">shortEdges</item>
        <item name="android:windowBackground">@color/colorAccent</item>
        <item name="android:windowFullscreen">true</item>
        <!--Android 5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色-->
        <item name="android:statusBarColor" tools:ignore="NewApi">#00000000</item>
    </style>

  这里我还修改了颜色代码,换成了粉色的:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#FFB6C1</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#FFB6C1</color>
    <color name="red_trans">#FFB6C1</color>
</resources>

  在res/values/下新增dimens.xml文件用于控件大小配置:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="dp_40">40dp</dimen>
    <dimen name="dp_80">80dp</dimen>
    <dimen name="dp_30">30dp</dimen>
    <dimen name="dp_10">10dp</dimen>
    <dimen name="dp_120">120dp</dimen>
    <dimen name="dp_35">35dp</dimen>
    <dimen name="dp_12">12dp</dimen>
    <dimen name="dp_5">5dp</dimen>
    <dimen name="dp_7">7dp</dimen>
    <dimen name="sp_14">14sp</dimen>
    <dimen name="sp_16">16sp</dimen>
    <dimen name="sp_17">17sp</dimen>
    <dimen name="dp_15">15dp</dimen>
    <dimen name="dp_60">60dp</dimen>
    <dimen name="dp_45">45dp</dimen>
    <dimen name="dp_20">20dp</dimen>
    <dimen name="dp_50">50dp</dimen>
    <dimen name="sp_18">18sp</dimen>
    <dimen name="dp_25">25dp</dimen>
    <dimen name="dp_2">2dp</dimen>
    <dimen name="dp_55">55dp</dimen>
    <dimen name="sp_12">12sp</dimen>
    <dimen name="sp_15">15sp</dimen>
    <dimen name="sp_22">22sp</dimen>
    <dimen name="dp_3">3dp</dimen>
    <dimen name="dp_200">200dp</dimen>
    <dimen name="dp_4">4dp</dimen>
    <dimen name="dp_160">160dp</dimen>
    <dimen name="dp_64">64dp</dimen>
    <dimen name="dp_8">8dp</dimen>
    <dimen name="dp_1">1dp</dimen>
    <dimen name="sp_13">13sp</dimen>
    <dimen name="dp_100">100dp</dimen>
    <dimen name="dp_70">70dp</dimen>
    <dimen name="dp_130">130dp</dimen>
    <dimen name="dp_140">140dp</dimen>
    <dimen name="dp_150">150dp</dimen>
    <dimen name="dp_110">110dp</dimen>
    <dimen name="sp_24">24sp</dimen>
    <dimen name="sp_21">21sp</dimen>
    <dimen name="dp_13">13dp</dimen>
    <dimen name="sp_10">10sp</dimen>
    <dimen name="sp_11">11sp</dimen>
    <dimen name="dp_170">170dp</dimen>
    <dimen name="dp_165">165dp</dimen>
    <dimen name="dp_320">320dp</dimen>
    <dimen name="dp_640">640dp</dimen>
    <dimen name="dp_250">250dp</dimen>
    <dimen name="dp_90">90dp</dimen>
    <dimen name="dp_220">220dp</dimen>
    <dimen name="dp_22">22dp</dimen>
    <dimen name="dp_27">27dp</dimen>
    <dimen name="dp_48">48dp</dimen>
    <dimen name="dp_28">28dp</dimen>
    <dimen name="dp_18">18dp</dimen>
    <dimen name="dp_23">23dp</dimen>
    <dimen name="dp_58">58dp</dimen>
    <dimen name="dp_75">75dp</dimen>
    <dimen name="dp_6">6dp</dimen>
    <dimen name="dp_65">65dp</dimen>
    <dimen name="dp_300">300dp</dimen>
    <dimen name="dp_280">280dp</dimen>
    <dimen name="dp_288">288dp</dimen>
    <dimen name="dp_290">290dp</dimen>
    <dimen name="sp_26">26sp</dimen>
    <dimen name="sp_30">30sp</dimen>
    <dimen name="sp_28">28sp</dimen>
    <dimen name="dp_190">190dp</dimen>
    <dimen name="dp_52">52dp</dimen>
    <dimen name="dp_46">46dp</dimen>
    <dimen name="dp_39">39dp</dimen>
    <dimen name="dp_38">38dp</dimen>
    <dimen name="dp_42">42dp</dimen>
    <dimen name="sp_20">20sp</dimen>
    <dimen name="dp_85">85dp</dimen>
    <dimen name="dp_105">105dp</dimen>
    <dimen name="dp_95">95dp</dimen>
    <dimen name="dp_230">230dp</dimen>
    <dimen name="dp_235">235dp</dimen>
    <dimen name="dp_240">240dp</dimen>
    <dimen name="dp_180">180dp</dimen>
    <dimen name="dp_56">56dp</dimen>
    <dimen name="dp_32">32dp</dimen>
    <dimen name="dp_11">11dp</dimen>
    <dimen name="sp_9">9sp</dimen>
    <dimen name="dp_400">400dp</dimen>
    <dimen name="dp_450">450dp</dimen>
    <dimen name="dp_24">24dp</dimen>
    <dimen name="dp_26">26dp</dimen>
    <dimen name="dp_590">590dp</dimen>
    <dimen name="dp_295">295dp</dimen>
    <dimen name="dp_195">195dp</dimen>
    <dimen name="dp_74">74dp</dimen>
    <dimen name="dp_53">53dp</dimen>
    <dimen name="fab_margin">16dp</dimen>
    <dimen name="dp_260">260dp</dimen>
    <dimen name="dp_1000">1000dp</dimen>
    <dimen name="dp_210">210dp</dimen>
    <dimen name="dp_185">185dp</dimen>
    <dimen name="dp_33">33dp</dimen>
</resources>

修改启动页

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/red_trans">
    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@drawable/launcher_back" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_below="@+id/image"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="@string/app_name"
        android:layout_marginTop="16dp"
        android:textStyle="bold"
        android:textSize="18sp"
        android:textColor="#2c2c2c"/>
</RelativeLayout>

  放一下图标资源链接: 提取码 tobe。
  编写静态方法帮助类:

public class StaticMethodUtils {

      //权限组
     public static final String[] ARR_NEED_PERMISSIONS = new ArrayList<String>() {
        {

            add(Manifest.permission.CAMERA);
            add(Manifest.permission.READ_PHONE_STATE);
            add(Manifest.permission.READ_EXTERNAL_STORAGE);
            add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
            add(Manifest.permission.CALL_PHONE);

        }
    }.toArray(new String[0]);

}

  修改SplashActivity继承BaseActivity,启动页的启动动画我没做,就是简单的展示2s图标页面,有兴趣的可以自行研究一下:

public class SplashActivity extends BaseActivity {

    //计时器
    private CountDownTimer countDownTimer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        if (!isTaskRoot()) {
            final Intent intent = getIntent();
            final String intentAction = intent.getAction();
            if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
                finish();
                return;
            }
        }
        setContentView(R.layout.activity_splash);

    }

    @Override
    protected BasePresenter onCreatePresenter() {
        return null;
    }

    @Override
    protected void initData() {
        PermissionX.init(this)
                .permissions(ARR_NEED_PERMISSIONS)
                .request((allGranted, grantedList, deniedList) -> {
                    if (allGranted){
                        //开始倒计时
                        startCountDown();
                    }else {
                        ToastUtils.show("缺少如下权限"+deniedList);
                    }
                });
    }

    private void startCountDown() {
        countDownTimer = new CountDownTimer(2000,1000) {
            @Override
            public void onTick(long millisUntilFinished) {

            }

            @Override
            public void onFinish() {
               //倒计时结束2s

              //  startActivity(LoginActivity.class);
             //   finish();
            }
        };
        countDownTimer.start();
    }

    @Override
    protected void initModule() {

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //防止异常奔溃造成内存泄露
        if (countDownTimer !=null){
            countDownTimer.cancel();
            countDownTimer = null;
        }
    }

    @Override
    public void finish() {
        super.finish();
        if (countDownTimer !=null){
            countDownTimer.cancel();
            countDownTimer = null;
        }
    }
}

复用的标题栏

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/title"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dp_45">
    <ImageView
        android:id="@+id/iv_back"
        android:layout_width="@dimen/dp_30"
        android:layout_height="@dimen/dp_30"
        android:layout_centerVertical="true"
        android:layout_marginStart="@dimen/dp_15"
        android:layout_marginTop="@dimen/dp_5"
        android:background="@mipmap/back_title"
        android:scaleY="0.9"
        tools:ignore="RtlCompat" />
    <TextView
        android:id="@+id/tv_title_center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:layout_marginStart="@dimen/dp_15"
        android:gravity="center"
        android:singleLine="true"
        android:textColor="#333333"
        android:textStyle="bold"
        android:textSize="@dimen/sp_18"
        android:visibility="gone"
        android:typeface="monospace"

        tools:ignore="RtlCompat" />

</RelativeLayout>

  最后别忘记将splashActivity设置为第一启动页,给splashActivity设置主题android:theme="@style/ThemeSplash"
  下一篇Retrofit+okhtp3实现登录功能( 简易音乐 三 )
  有问题欢迎批评指正,觉得不错的话也请点个赞

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪の星空朝酱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值