java.lang.RuntimeException:Unable to start activity ComponentInfo{com.meizu.beautify/com.my.viewc.Ma
来源:互联网 发布:宋太宗997 知乎 编辑:程序博客网 时间:2024/04/29 16:49
在使用fragment的时候,遇到如下的bug:
java.lang.RuntimeException:Unable to start activity ComponentInfo{com.meizu.beautify/com.my.viewc.MainActivity}: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.meizu.main.ResourcesDetailedActivity: make sure class name exists, is public, and has an empty constructor that is public
无法定位到哪一行有错误,只能各种百度,最后发现有一个前辈说的如下:
这才发现原来是FragmentActivity的问题。通过Message查阅源码可知,使用Fragment时,不能自己写带参数的构造函数,因为系统默认调用的是无参构造函数 newResourcesDetailedActivity(String cc);否则在创建Fragment时,系统会调用无参构造函数,而你重新写了带参数的构造函数,导致系统找不到这个方法,最后就出现java.lang.NoSuchMethodException:<init> []而且找不到报错的代码行,只要将其改为:newResourcesDetailedActivity();就不会再出现异常了,然后使用其他的方法传递参数或者对象,问题搞定。
我测试的结果是登陆我的app,手机放置,打开很多其他的app之后,内存不足,fragment依托的总之就是说Acitivity被被销毁了,就会出现上述bug,按照前辈所说我给每个fragment类都添加上无参构造函数。
这是另一个前辈遇到的类似问题的解释:
这样做好后看似没问题。但是比较低端的手机内存不足的时候会造成fragment重叠的情况。实是由Activity被回收后重启所导致的Fragment重复创建和重叠的问题。在Activity onCreate()中添加Fragment的时候一定不要忘了检查一下savedInstanceState:多个Fragment重叠则可以这样处理:通过FragmentManager找到所有的UI Fragment,按需要show()某一个Fragment,hide()其他即可!为了能准确找出所需的Fragment,所以在add()或者replace() Fragment的时候记得要带上tag参数,因为一个ViewGroup 容器可以依附add()多个Fragment,它们的id自然是相同的。复制代码/** * 状态检测 用于内存不足的时候保证fragment不会重叠 * * @param savedInstanceState */ private void stateCheck(Bundle savedInstanceState) { if (savedInstanceState == null) { fm = getFragmentManager(); FragmentTransaction fts = fm.beginTransaction(); AnimationFragment af = new AnimationFragment(); mContent = af; fts.add(R.id.content_frame, af); fts.commit(); } else { AnimationFragment af = (AnimationFragment) getFragmentManager() .findFragmentByTag(tags[0]); PlainFragment pf = (PlainFragment) getFragmentManager() .findFragmentByTag(tags[1]); RecordFragment rf = (RecordFragment) getFragmentManager() .findFragmentByTag(tags[2]); InformationFragment inf = (InformationFragment) getFragmentManager() .findFragmentByTag(tags[3]); TestingFragment tf = (TestingFragment) getFragmentManager() .findFragmentByTag(tags[4]); getFragmentManager().beginTransaction().show(af).hide(pf).hide(rf) .hide(inf).hide(tf).commit(); } }复制代码
这是第三个前辈的分析:
自从在Android 3.0引入Fragment以来,它被使用的频率也随之增多。Fragment带来的好处不言而喻,解决了不同屏幕分辨率的动态和灵活UI设计。但是在Activity管理多个Fragment中,通常会遇到这些问题:1、Fragment的状态保存2、Fragment的重影当然,这些问题也一直出现我的开发过程中,虽然有时候通过各种手段也能解决一些问题,但是总是同时完美解决这两个问题。近来因为项目需要,查阅了很多官方资料(Android官方资料也慢慢有中文资料了,我大Google果然是Don't be evil,扯远了~~),终于彻底解决了这些问题。设备:nexus 5条件:1、打开“不保留活动”(开发者选项里,主要用于模拟Activity被及时回收)2、关闭“不保留活动”(正常状态下)结果:目前没发现问题,由于设备有限,大家如果发现在其他设备上有问题,请在下方回帖!首先我先来解释下上面问题出现的原因:1、有时候,我们需要在多个Fragment间切换,并且保存每个Fragment的状态。官方的方法是使用replace()来替换Fragment,但是replace()的调用会导致Fragment的onCreteView()被调用,所以切换界面时会无法保存当前的状态。因此一般采用add()、hide()与show()配合,来达到保存Fragment的状态。以下为代码片段:private void setTabSelection(int position) { //记录position this.position = position; //更改底部导航栏按钮状态 changeButtonStatus(position); FragmentTransaction transaction = fragmentManager.beginTransaction(); // 先隐藏掉所有的Fragment,以防止有多个Fragment显示在界面上的情况 hideFragments(transaction); switch (position) { case TAB_HOME: btnHomePager.setSelected(true); btnShoppingCart.setSelected(false); btnMine.setSelected(false); if (homeFragment == null) { homeFragment = new HomePagerFragment(); transaction.add(R.id.fragment_container, homeFragment); } else { transaction.show(homeFragment); } break; case TAB_SHOP: btnHomePager.setSelected(false); btnShoppingCart.setSelected(true); btnMine.setSelected(false); if (shoppingFragment == null) { shoppingFragment = new ShoppingCartFragment(); transaction.add(R.id.fragment_container, shoppingFragment); } else { transaction.show(shoppingFragment); } break; case TAB_MINE: btnHomePager.setSelected(false); btnShoppingCart.setSelected(false); btnMine.setSelected(true); if (mineFragment == null) { mineFragment = new MineFragment(); transaction.add(R.id.fragment_container, mineFragment); } else { transaction.show(mineFragment); } break; } transaction.commitAllowingStateLoss(); }2、第二个问题的出现正是因为使用了Fragment的状态保存,当系统内存不足,Fragment的宿主Activity回收的时候,Fragment的实例并没有随之被回收。Activity被系统回收时,会主动调用onSaveInstance()方法来保存视图层(View Hierarchy),所以当Activity通过导航再次被重建时,之前被实例化过的Fragment依然会出现在Activity中,然而从上述代码中可以明显看出,再次重建了新的Fragment,综上这些因素导致了多个Fragment重叠在一起。我尝试了很多种方法去解决这个问题,比如:在onSaveInstance()里面去remove()所有非空的Fragment,然后在onRestoreInstanceState()中去再次按照问题一的方式创建Activity。当我处于打开“不保留活动”的时候,效果非常令人满意,然而当我关闭“不保留活动”的时候,问题却出现了。当转跳到其他Activity、打开多任务窗口、使用Home回到主屏幕再返回时,发现根本没有Fragment了,一篇空白。于是跟踪下去,我调查了onSaveInstanceState()与onRestoreInstanceState()这两个方法。原本以为只有在系统因为内存回收Activity时才会调用的onSaveInstanceState(),居然在转跳到其他Activity、打开多任务窗口、使用Home回到主屏幕这些操作中也被调用,然而onRestoreInstanceState()并没有在再次回到Activity时被调用。而且我在onResume()发现之前的Fragment只是被移除,并不是空,所以就算你在onResume()中执行问题一中创建的Fragment的方法,同样无济于事。所以通过remove()宣告失败。接着通过调查资料发现Activity中的onSaveInstanceState()里面有一句super.onRestoreInstanceState(savedInstanceState),Google对于这句话的解释是“Always call the superclass so it can save the view hierarchy state”,大概意思是“总是执行这句代码来调用父类去保存视图层的状态”。其实到这里大家也就明白了,就是因为这句话导致了重影的出现,于是我删除了这句话,然后onCreate()与onRestoreInstanceState()中同时使用问题一中的创建Fragment方法,然后再通过保存切换的状态,发现结果非常完美。代码如下://记录Fragment的位置private int position = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_index); setTabSelection(position);}@Overrideprotected void onRestoreInstanceState(Bundle savedInstanceState) { position = savedInstanceState.getInt("position"); setTabSelection(position); super.onRestoreInstanceState(savedInstanceState);}@Overrideprotected void onSaveInstanceState(Bundle outState) { //记录当前的position outState.putInt("position", position);}记录于此,希望能帮助到一些正遇到这种问题的朋友
我用的红米手机,也是属于比较低端,内存很小,同时开启多个app,就会出现上述问题,另一个重现方式是进入设置里面,有一个开发者选项,选择应用中的不保留活动,也就是一旦应用在后台便会杀死activity,这样一下子就会重现该问题,解决方案如下:
当由于内存不足,点击我的app时,在fragment绑定的activity的oncreate方法内,对 savedInstanceState进行判断,如果不为空,则跳转到登陆界面,如下代码:
进行判断,如果不为空,则跳转到登陆界面,如下代码:@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// setTheme(android.R.style.Theme_DeviceDefault_Light_NoActionBar_Fullscreen);
if (savedInstanceState != null) {
System.out.println("有没有执行这句话,用来内存不足,跳转回登陆界面");
Intent intent = new Intent(FragmentManagerActivity.this,
LoginActivity.class);
startActivity(intent);
finish();
} else {
setDefaultFragment();
}
这样避免app‘退出,但么有实现恢复之前状态的功能。
还有google上的另一位前辈给的方案:
runOnUiThread(new Runnable() { @Override public void run() {if(!isFinishing()){showDialog ( new AlertDialog.Builder(MainActivity.this).setTitle(R.string.dialogTitle).setMessage(R.string.dialogText).setCancelable(false).setPositiveButton(R.string.txtOk, new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) { // whatever...}}).create() ); } }});
- java.lang.RuntimeException:Unable to start activity ComponentInfo{com.meizu.beautify/com.my.viewc.Ma
- java.lang.RuntimeException: Unable to start activity ComponentInfo{com.clm.activity/com.clm.activity
- java.lang.RuntimeException: Unable to start activity ComponentInfo{ com.xuqinjun.hello01/com.xuqinj
- java.lang.RuntimeException: Unable to start activity ComponentInfo{com.wwj.toggle/com.wwj.toggle.Set
- java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.FirstView/com.example
- java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.w/com.example.w.MainA
- java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.xiaoshuo01/com.exampl
- 错误:java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.tongzhi
- java.lang.RuntimeException: Unable to start activity ComponentInfo{com.esri.arcgis.android.samples.h
- java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.bingbing.littlefarmer
- android中使用fragment时出现如下错误 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.fra
- java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.gaobo.e5community/com.g
- java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.irun/com.exampl
- java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.gditc.mmms/com.gditc.mm
- java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.yf.huiju/com.yf.huiju.a
- java.lang.RuntimeException: Unable to start activity ComponentInfo
- java.lang.RuntimeException: Unable to start activity ComponentInfo解决方案
- java.lang.RuntimeException: Unable to start activity ComponentInfo解决方案
- poj2773
- Android layout属性大全
- poj2478
- BLE-NRF51822教程1-常用概念
- java 异常
- java.lang.RuntimeException:Unable to start activity ComponentInfo{com.meizu.beautify/com.my.viewc.Ma
- 商品的页面
- WKWebView VS UIWebView
- typedef 与#define的区别
- Centos7 Java配置
- nginx做负载均衡的常用配置
- 生成唯一序列号 Unique ID
- C语言总结(一)
- 配置jdk和tomcat