起因
在App开发的当下,在满足功能需求的基础上,用户体验也显得愈发的重要。启动页和广告页则是用户体验上比较重要的一环,下面就跟大家分享下启动页和广告页的结合。拒绝白屏!拒绝糟糕切换体验!
启动页
如果我们直接进入主页,而没有启动页的话,那么肯定是会有白屏的,这对用户是极其糟糕的体验。那么,原因呢?是因为我们的activity在oncreate()生命周期的setContentView()。该方法内部做的是xml布局的导入,而我们xml布局的解析和初始化肯定是个耗时的过程,在动作完毕之前。我们页面没有内容呈现,自然就是白屏的效果。
广告图
app开发一般是会在启动页加入广告图的。一来,我们可以推广各种自己的东西,支持业务。二来,我们可以推广其他广告。类似网页云音乐,知乎等app都是有广告图的,而且效果相当不错。
效果
下面,我先展示下自己Demo效果(数据是模拟的)。
主体效果
![](https://img.haomeiwen.com/i11226595/0e73bff32faa5051.gif)
进入广告详情、跳过广告
![](https://img.haomeiwen.com/i11226595/36e031fe005d65bf.gif)
流程
一、设置主题
我上面有提到过,我们setContentView()的xml读入是耗时的,会引起白屏。我们需要启动页。
那么启动页的实现逻辑呢?
首先,我们需要定义一个SplashActivity(名字随意)。然而,这个SplashActivity的setContentView()同样是耗时的。意义呢?意义:在SplashActivity完成大量的逻辑工作,白屏优化包括在逻辑里面。最后,我们进入首页面。
针对白屏,我们没法加速setContentView()的xml读入。就算能‘加速’(减少xml节点),白屏还是会出现的,出发点不在这里。
我们需要设置主题,主题的加载是第一位的。而且耗时极短(忽略不计)。
//该主题继承了我们自己的MyBaseTheme主题,
//主要通过windowBackground指定了启动页图片,windowFullscreen指定了全屏。
//drawable/splash目录的图片即是我们的启动页图片
<style name="SplashTheme" parent="MyBaseTheme">
<item name="android:windowBackground">@drawable/splash</item>
<item name="android:windowFullscreen">true</item>
</style>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/MyBaseTheme">
<activity
//指定了主题
android:name=".activities.SplashActivity"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
//主页
<activity android:name=".activities.MainActivity" />
//广告内容展示页
<activity android:name=".activities.ADActivity" />
//下载图片(然后存入本地)的intentService
<service android:name=".service.ADIntentService"/>
</application>
通过上面的操作,我们的启动页就算完成了。哈哈哈,简单吧~
书写SplashActivity逻辑
上面讲到SplashActivity是借用主题实现了启动页。下来我们还需要在SplashActivity完成一系列逻辑。我这边分步骤说明。
一:我们要判断启动页展示之后的逻辑,显示广告还是直接进入首页。
二:显示广告的逻辑依赖接口请求,我们需要做成功、失败和超时处理。
三:广告图片的本地路径是否存在。如果不存在,则开启intentService下载图片,并进入首页。如果存在,则显示图片。
四:图片显示倒计时三秒自动挑转到首页。
五:图片在显示中,如果图片被点击则进入详情页面。如果点击跳过按钮则直接进入首页。
上面大致介绍了主体逻辑,下面我们上代码,各位思路跟上哈~
首先是onCreate相关:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//状态栏处理
invadeStatusBar();
//就是类似boss启动页的底部版本文字(不重要)
addVersionView();
//初始化网路,根据后端状态判断是否需要显示广告页,以及更新广告等
initNet();
}
这边是网络细节:
private void initNet() {
//此处应该是一个数据获取,请求后端广告接口拿到一系列数据。
//应该设置连接和读写超时时间。一旦超时,直接进入主页面。不会让用户过久等待
//我这边模拟个网络操作,拿到url
Request request = new Request.Builder().url("https://www.baidu.com").build();
OkHttpClient client = new OkHttpClient.Builder()
//一秒钟连接超时、读超时、写超时(避免过长时间启动页面等待)
.connectTimeout(1000, TimeUnit.MILLISECONDS)
.readTimeout(1000, TimeUnit.MILLISECONDS)
.writeTimeout(1000, TimeUnit.MILLISECONDS)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//失败响应 包括超时等等,直接进入首页
startActivity(MainActivity.class);
finish();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//成功响应 应该从里面拿到数据,我采用模拟图片url
//广告图片url
String imgUrl = "http://img.zcool.cn/community/01e51e581074cda84a0d304ff02d18.png@1280w_1l_2o_100sh.png";
//广告标题
String title = "百度首页";
//广告内容地址(webView呈现)
String contentUrl = "http://www.baidu.com";
//最好将ad广告对象封装起来,结构有广告图片url,广告标题,广告内容url;
mAdBean = new ADBean(title, imgUrl, contentUrl);
runOnUiThread(new Runnable() {
@Override
public void run() {
//实际还需判断是否有广告、是否显示(这边只是接口正常响应)
adWork(mAdBean);
}
});
}
});
}
如果接口正常响应并且有数据需要显示:
private void adWork(ADBean bean) {
// 如果图片已经下载到了本地,那么就加载该图片。如果没有的话,就下载并进入首页
String adFilePath = SPManager.getADFilePath(this);
//本地没有图片url对应的本地路径(之前没有下载该图片)
if (TypeUtil.isBlank(adFilePath)) {
//图片下载后路径会存入sp。之后通过sp拿取数据。
// 不过建议,本地数据库存多个广告数据(可以切换显示广告),多广告优先级跟你们后端商定.
//开启intentService下载图片.并存入本地.用sp来获取图片本地路径
Intent intent = new Intent(this, ADIntentService.class);
intent.putExtra("downUrl", bean.getImgUrl());
startService(intent);
//同时进入首页
startActivity(MainActivity.class);
//toast(博客介绍使用,实际开发中应该删除)
showToast("本地无图片资源,启动service下载图片");
finish();
return;
}
//之前已经下载了该图片,显示广告图片,点击打开广告的activity,加载广告内容
initViews(adFilePath);
}
广告图显示相关(仍在SplashActivity):
private void initViews(String adValue) {
setContentView(R.layout.ad_layout);
final View layout = findViewById(R.id.splash_rl);
ImageView imageView = (ImageView) findViewById(R.id.splash_iv);
final Button button = (Button) findViewById(R.id.splash_bn);
if (!TypeUtil.isBlank(adValue)) {
//广告图覆盖了主题背景(启动图片)
Glide.with(this).load(adValue).placeholder(R.drawable.splash).crossFade().into(new GlideDrawableImageViewTarget(imageView) {
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {
super.onResourceReady(resource, animation);
layout.setVisibility(View.VISIBLE);
button.setVisibility(View.VISIBLE);
}
});
}
//显示广告图片,开始倒计时
mDownTimer = new CountDownTimer(4000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
button.setText("跳过 " + millisUntilFinished / 1000 + "s");
}
@Override
public void onFinish() {
button.setText("跳过 " + 0 + "s");
if (!mIsStopTimer) {
startActivity(MainActivity.class);
finish();
}
}
};
mDownTimer.start();
//注意,如果点击进入广告内容activity,中断mDownTimer的计时,防止首页打开
button.setOnClickListener(this);
layout.setOnClickListener(this);
}
点击事件相关:
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.splash_bn:
//toast(博客介绍使用,实际开发中应该删除)
showToast("点击跳过");
stopDownTimer();
startActivity(MainActivity.class);
finish();
break;
case R.id.splash_rl:
//toast(博客介绍使用,实际开发中应该删除)
showToast("点击广告图片,进入详情");
stopDownTimer();
Intent intent = new Intent(this, ADActivity.class);
intent.putExtra(ConstantUtil.Intent.AD_TITLE, mAdBean.getTitle());
intent.putExtra(ConstantUtil.Intent.AD_CONTENT_URL, mAdBean.getContentUrl());
startActivity(intent);
finish();
break;
}
}
完工~
总结
上面就是主体逻辑以及主要代码的实现啦。大家看完之后有任何疑问,请评论留言。如果觉得对你有帮助的话,希望大家点赞、评论和转发。帮助到更多的人,也支持我继续创作。谢谢大家~
我这边留下仓库地址,方便大家交流以及移植代码.
Github地址:https://github.com/HoldMyOwn/Splash
网友评论