【问题标题】:How many levels of Activity/Fragments can I start?我可以开始多少级别的活动/片段?
【发布时间】:2015-05-19 06:27:06
【问题描述】:

当我从 FragmentActivity/Fragment 组合的第 3 级启动时,我在启动从图库中选择图像的 Activity 时遇到问题。如果我从第一级或第二级开始,它就可以工作。 在应用程序中,最多有 5 个级别的 FramentActivity/Fragment 组合运行没有问题,但我没有启动 Activity 来从中挑选图像。

我可以启动的 FramentActivity/Fragment 组合是否有最高级别?还是我做错了什么?

FragmentActivity 像这样启动 Fragment:

public class MyActivity extends FragmentActivity
{
private MyFragment _fragment;
...

@Override
public void onCreate( Bundle savedInstanceState )
{
    super.onCreate( savedInstanceState );
    setContentView( R.layout.simple_fragment_container_activity );

    // create the fragment to show
    FragmentManager fm = getSupportFragmentManager();
    _fragment = (MyFragment)fm.findFragmentById( R.id.fragment_container );

    // If the Fragment is non-null, then it is currently being retained across a configuration change.
    if( _fragment == null )
    {
        _fragment = new MyFragment();

        // start the new fragment
        FragmentTransaction ft = fm.beginTransaction();
        ft.add( R.id.fragment_container, _fragment );
        ft.commit();
    }
}

片段代码为:

@Override
public void onCreate( Bundle savedInstanceState )
{
    super.onCreate( savedInstanceState );

    // retain this fragment across configuration changes
    setRetainInstance( true );
}
@Override
public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState )
{
    View v = inflater.inflate( R.layout.my_fragment, container, false );
    ...
    return v;
}

在按钮的 OnClickListener 中,我像这样启动图像选择器:

Intent intent = new Intent( Intent.ACTION_GET_CONTENT );
intent.setType( "image/*" );
startActivityForResult( intent, 20 );           

只要我关闭图像选择器(无论是否选择图像),我的应用都会在恢复之前崩溃。 onActivityResult 方法有时被完全调用,有时被部分调用。它暂时只记录图像路径:

if( resultCode != Activity.RESULT_OK ) return;
if( requestCode == 20 )
{
    Uri selectedImage = intent.getData();
    Log.w( null, "image picked: " + selectedImage.toString() );
}

崩溃将其写入 LogCat 并且在我的代码 IMO 中不会发生:

05-19 08:18:19.210: D/AndroidRuntime(24592): Shutting down VM
05-19 08:18:19.210: W/dalvikvm(24592): threadid=1: thread exiting with uncaught exception (group=0x41826da0)
05-19 08:18:19.220: E/AndroidRuntime(24592): FATAL EXCEPTION: main
05-19 08:18:19.220: E/AndroidRuntime(24592): Process: ch.infero.testapp, PID: 24592
05-19 08:18:19.220: E/AndroidRuntime(24592): java.lang.RuntimeException: Unable to resume activity {ch.infero.testapp/ch.infero.testapp.settings.MyActivity}: android.database.StaleDataException: Attempted to access a cursor after it has been closed.
05-19 08:18:19.220: E/AndroidRuntime(24592):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2946)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2975)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1307)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at android.os.Handler.dispatchMessage(Handler.java:102)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at android.os.Looper.loop(Looper.java:157)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at android.app.ActivityThread.main(ActivityThread.java:5356)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at java.lang.reflect.Method.invokeNative(Native Method)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at java.lang.reflect.Method.invoke(Method.java:515)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at dalvik.system.NativeStart.main(Native Method)
05-19 08:18:19.220: E/AndroidRuntime(24592): Caused by: android.database.StaleDataException: Attempted to access a cursor after it has been closed.
05-19 08:18:19.220: E/AndroidRuntime(24592):    at android.database.BulkCursorToCursorAdaptor.throwIfCursorIsClosed(BulkCursorToCursorAdaptor.java:64)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at android.database.BulkCursorToCursorAdaptor.requery(BulkCursorToCursorAdaptor.java:133)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at android.database.CursorWrapper.requery(CursorWrapper.java:186)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at android.app.Activity.performRestart(Activity.java:5471)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at android.app.Activity.performResume(Activity.java:5497)
05-19 08:18:19.220: E/AndroidRuntime(24592):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2936)
05-19 08:18:19.220: E/AndroidRuntime(24592):    ... 10 more

【问题讨论】:

  • 没有最大值。但是错误在堆栈跟踪中得到了完美的解释:android.database.StaleDataException: Attempted to access a cursor after it has been closed.

标签: android android-fragments crash fragment android-fragmentactivity


【解决方案1】:

不,没有这样的明确限制。您遇到的问题是,当您的一个活动回到前面时(似乎在 MyActivity.onResume() 中),尽管它之前已经关闭,但数据库游标被重用。

【讨论】:

  • 我没有在调用图像选择器的第三个活动中使用光标。那时第一级还是第二级重要吗?
  • 您的代码中是否有数据库游标?
  • 是的,但不在第 2 或第 3 级活动/片段中。只有第 3 级回到前面。每个级别都完全涵盖了启动它的活动。因此,在 on it 调用关闭之前不应恢复启动活动
  • 崩溃肯定与那个光标有关。如果没有完整的代码,很难说出更多细节。
【解决方案2】:

我找到了原因...希望它可以帮助遇到同样问题的其他人。

在启动图像选择器活动的片段的 onCreate 方法中,我有这段代码 sn-p 来读出可用铃声的名称和 uri:

...
RingtoneManager rm = new RingtoneManager( getActivity() );
rm.setType( RingtoneManager.TYPE_NOTIFICATION );
Cursor c = rm.getCursor();
while( c.moveToNext() )
{
    String title = c.getString( RingtoneManager.TITLE_COLUMN_INDEX );
    String id = c.getString( RingtoneManager.ID_COLUMN_INDEX );
    String uri = c.getString( RingtoneManager.URI_COLUMN_INDEX );
    // ...put it to a local list
}
c.close()       // <<<< this line is the problem !!!
...

嗯,RingtoneManager.getCursor() 的帮助文本说明了这一点:

返回所有可用铃声的光标。返回的游标 每次调用此方法时都会返回相同的光标,所以 不要 Cursor.close() 光标。光标可以是 Cursor.deactivate() 安全。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多