您的位置:首页 > 移动开发 > Android开发

android启动页面

2016-09-08 00:56 141 查看
1.使用Activity的方式,

缺点:沉重,容易造成动画捕捉间隙,当然可以特殊处理了,

但是它还有个最致命的缺陷.由于国内部分APP越来越流氓,6.0之下的Android一直受到无限后台重启的困扰,所以当手机内存不足,遇上GC的时候,你就会发现,你退出了启动页Activity,但是,却并未进入主页面,又或者用户会看当很长时间的App黑屏或者上一个APP的界面,又甚至在某些处理不当的App上,主页面首先运行,而当用户退出之后,启动页依然存在,又在去启动主页面,更甚者可能造成手机重启,(这个问题是无法避免的,尽管你设置了透明主题也无用),现在普遍国内的APP都采用这种启动页模式,总体而言,以我使用的经验而言内存不足必出黑屏.

优点:出Bug也不至于搞死APP,相对来说比较安全

推荐用于快速开发的APP,因为一般这类APP,没有那么多的时间,不要求很细心的设计

2.使用WindowManager,

优点:能够在Application环境启动(WindowManager.Toast),中等轻量,(但是,如果启动也需要与用户交互,需要版本匹配)

缺点:双页面(有时候这也会成为其优点)

推荐适合于小区域,高版本API标准的APP.

3.使用ViewRootImpl,也就是传说中的根View,(findView(android.R.id.content).getRootView)

优点:极其轻量,不会造成双页面(一体化视觉效果),也不会GC黑屏,并且你可以在每个Activity启动时插入启动页,而不必担心,GC黑屏的风险

缺点,容易触发hwui(硬件加速)中的BUG,会导致本地泄漏(可能是我测试机为4.4.2版本对硬件加速支持不是很好的原因),为什么说可能呢,这家伙就像是个孩子,一点代码让它不爽,就会搞死你APP并且不会出现Log信息,很操蛋.我发现一个.就是你在使用该启动页的时候,底层的View,也就是被它覆盖的视图,通常是我们通过Activity.setContentView的那个视图,绝对不能进行大量的绘制工作,也就是说,绝对不能不断的postInvaild(10)等,如果你有特效在哪里,必须要在remove了该启动页的View之后再来进行Post,否则,很操蛋.这东西绝对在不确定的时间直接搞死你的App

推荐用于重视软件设计与交互的App

4.自己定义顶层ContentView,自己搞定,

其实以上四种,最好用的还是第三种,但是,对你的代码水平要求很高

下面仅仅介绍第二种方式>

private void initLaunchPage() {
LaunchPage page = onNewLaunchPage();
if (page != null) {
ViewGroup root = getRootParent();
if (root == null) {
Log.e(TAG, "parent no found !");
return;
}
View view = page.onPageCreate(this);
if (view != null) {
if (page.hasFullScreen()) {
if (VERSION.SDK_INT >= 16) {
mLauchViewFlag = View.SYSTEM_UI_FLAG_FULLSCREEN;
}
mLauchViewFlag |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
mLauchWindowFlags = WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
view.setSystemUiVisibility(mLauchViewFlag);
}

WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
if (wm == null) {
throw new NullPointerException("WindowManager Null !");
}
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,LayoutParams.APPLICATION, mLauchWindowFlags, android.graphics.PixelFormat.RGBA_8888);
if (page.getAnimationId() > 0) {
params.windowAnimations = page.getAnimationId();
}
wm.addView(view, params);
mLaunchView = view;
}
}
}


Node>这篇文章修改了挺多,我也是为了证明这种启动页的可用性,

- 在Application环境下的该类型启动页.必须使用Toast类型,因为我们的Application Root Window 在调用Applcaition OnCreate 时并没有创建,所以我们不能使用任何Applcaition级别的类型,说实话,在Application环境下使用Toast窗体,启动速度要比Activity环境下快的多,

_在Activity环境下,可以设置Application类型,你可以在呼叫super.OnCreate的时候,初始化起始页.类似这样

@Override
protected final void onCreate(Bundle savedInstanceState) {
startLaunchPage();

setContentView(R.id.content);

super.onCreate(savedInstanceState);

}

public class PageLauncher {

private int mLauchViewFlag;

private LaunchPager mLaunchPage;
private View mLaunchView;
private Context mContext;

public PageLauncher(Context context, LaunchPager mPager) {
if (context == null) {
throw new NullPointerException("Context Can Not Null !");
}
if (mPager == null) {
throw new NullPointerException("LaunchPager Can Not Null !");
}
mContext = context;
mLaunchPage = mPager;
}

public static LaunchPager reloveLaunchPager(Context context) {
try {
Bundle bundle = null;
if (context instanceof Application) {
ApplicationInfo info = context.getPackageManager().getApplicationInfo(context.getPackageName(),
PackageManager.GET_META_DATA);
bundle = info.metaData;
} else if (context instanceof Activity) {
ActivityInfo info = context.getPackageManager().getActivityInfo(((Activity) context).getComponentName(),
PackageManager.GET_META_DATA);
bundle = info.metaData;
} else if (context instanceof Service) {
ComponentName mName = new ComponentName(context, context.getClass());
ServiceInfo info = context.getPackageManager().getServiceInfo(mName, PackageManager.GET_META_DATA);
bundle = info.metaData;
}
if (bundle != null) {
Object obj = bundle.get(LaunchPager.METE_NAME);
if (obj instanceof String) {
try {
return ((Class<LaunchPager>) context.getClassLoader().loadClass((String) obj)).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return null;
}

public static PageLauncher relovePageLauncher(Context context) {
LaunchPager mLaunchPager = reloveLaunchPager(context);
if (mLaunchPager != null) {
return new PageLauncher(context, mLaunchPager);
}
return null;
}

public static PageLauncher relovePageLauncher(Context context, LaunchPager pager) {
try {
if (pager != null) {
return new PageLauncher(context, pager);
}
} catch (Exception e) {
e.printStackTrace();
}
LaunchPager mLaunchPager = reloveLaunchPager(context);
if (mLaunchPager != null) {
return new PageLauncher(context, mLaunchPager);
}
return null;
}

public static PageLauncher relovePageLauncherCreate(Context context, LaunchPager pager) {
PageLauncher launcher = null;
try {
if (pager != null) {
launcher = new PageLauncher(context, pager);
launcher.startLaunchPage();
return launcher;
}
} catch (Exception e) {
e.printStackTrace();
}
LaunchPager mLaunchPager = reloveLaunchPager(context);
if (mLaunchPager != null) {
launcher = new PageLauncher(context, mLaunchPager);
launcher.startLaunchPage();
}
return launcher;
}

public synchronized void startLaunchPage() {
LaunchPager page = mLaunchPage;
if (page != null && mLaunchView == null) {
View view = page.onPageCreate(mContext);
if (view != null) {
int mLauchWindowFlags = 0;
if (page.hasFullScreen()) {
if (VERSION.SDK_INT >= 16) {
mLauchViewFlag = View.SYSTEM_UI_FLAG_FULLSCREEN;
}
if (VERSION.SDK_INT >= 14) {
mLauchViewFlag |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
mLauchWindowFlags = WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
try {
view.setSystemUiVisibility(mLauchViewFlag);
} catch (Throwable t) {
t.printStackTrace();
}
}

WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
if (wm == null) {
throw new NullPointerException("WindowManager Null !");
}

int type = LayoutParams.LAST_APPLICATION_WINDOW;
//如果是Applcation环境,你必须处理用户的按键状态,否则Toast将遮掩其他应用窗体
if (mContext instanceof Application) {
type = LayoutParams.TYPE_TOAST;
}
LayoutParams params = new LayoutParams(WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT, type, mLauchWindowFlags,
android.graphics.PixelFormat.RGBA_8888);
if (page.getAnimationId() > 0) {
params.windowAnimations = page.getAnimationId();
}
try {
wm.addView(view, params);
} catch (Exception e) {
e.printStackTrace();
}
mLaunchView = view;
}
}
}

public synchronized void removeLaunchPage() {
if (mLaunchView == null) {
return;
}
if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
if (mLaunchView != null) {
WindowManager wm = (WindowManager) mContext.getSy
afd9
stemService(Context.WINDOW_SERVICE);
if (wm == null) {
throw new NullPointerException("WindowManager Null !");
}
mLaunchPage.onPageDestory(mContext);
if (mLauchViewFlag > 0) {
mLaunchView.setSystemUiVisibility(0);
}
wm.removeViewImmediate(mLaunchView);
mLaunchView = null;
}
} else {
mLaunchView.post(new Runnable() {

@Override
public void run() {
removeLaunchPage();
}
});
}
}
}


public interface LaunchPager {
<span style="white-space:pre">		</span>public static final String PAGELAUNCHER = "Page_Launcher";
public static final String METE_NAME = "LaunchPager";
//可以加入onPageStart onPageResume 等方法
View onPageCreate(Context acter);

View onPageDestory(Context acter);

boolean hasFullScreen();

int getAnimationId();
}


private void initLaunchPage() {
if (mPageLauncher == null) {
mPageLauncher = PageLauncher.relovePageLauncherCreate(this, onNewLaunchPage());
}
}
@Override
public Object getSystemService(String name) {
if (ConfigPreferences.CONFIGPREFERENCE.equals(name)) {
return mConfigPreferences;
} else if (LaunchPager.PAGELAUNCHER.equals(name)) {
return mPageLauncher;
}
return super.getSystemService(name);
}

protected LaunchPager onNewLaunchPage() {
return null;
}


我修改了代码只需要在Application或者Activity中引用就可以,不过我建议在Activity或者Application中的Manifest中配置相关的LaunchPager类,并且完全可以在重写getSystenService(String name)方法,通过该方法获取上级的PageLauncher对象,这样配置的优点我感觉要比使用Activity具有更多的可扩展性,因为使用Activity总而言之太重
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android 启动页