Intent 不会从 Fragment 启动 Activity

Posted

技术标签:

【中文标题】Intent 不会从 Fragment 启动 Activity【英文标题】:Intent does not start Activity from Fragment 【发布时间】:2017-07-20 12:11:50 【问题描述】:

我在 android 中的片段中遇到了问题。 我有一个 Activity,它包含一个 Fragment,而 Fragment 又包含一个 ListView。 我已经向 ListView 注册了一个 onItemClickListener,当我在 Activity 中拥有 listView 权限时,它运行良好。但是,我需要将其包装在片段中。

因此,我现在调用getActivity(),而不是调用getContext(),就像到处推荐的那样。这实际上返回了正确的活动。 点击也被注册,因为我的 LogCat 正在打印。但意图从未开始。什么都没发生。 谁能告诉我我错过了什么?

这是我的代码:

_dealList.setOnItemClickListener(new AdapterView.OnItemClickListener()
        
            @Override
            public void onItemClick(AdapterView<?> parent, View v, int position, long id)
            
                Intent in = new Intent(getActivity(), DealView.class);
                in.putExtra("deal", position);
                in.putExtra("city", _citySearchBar.getText());
                startActivity(in);
                Log.d("BASE_FRAGMENT", "Activity should have been started here");
            
        );
    

此代码位于抽象类中,但将其移至子类并没有什么不同。

这是意图针对的 DealView 类:

public class DealView extends AppCompatActivity 
    private TextView _priceView;
    private TextView _descriptionView;
    private TextView _titleView;
    private TextView _storeView;
    private ImageView _imageView;
    private String _cityName;

    @Override
        protected void onCreate(Bundle savedInstanceState) 
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_deal_view);

            Intent fromDealSelection = getIntent();
            _cityName = fromDealSelection.getStringExtra("city");

            //Initializing the different components of the view
            _priceView = (TextView) findViewById(R.id.priceInputDealView);

            _descriptionView = (TextView) findViewById(R.id.dealDescriptionDealView);

            _titleView = (TextView) findViewById(R.id.dealTitleDealView);

            _storeView = (TextView) findViewById(R.id.storeDealView);

            _imageView = (ImageView) findViewById(R.id.imageViewDealView);

            _cityName = fromDealSelection.getStringExtra("city");

        

这是 LogCat 的输出:

03/01 09:42:23: Launching app
W/System: ClassLoader referenced unknown path: /data/data/de.coding.mb.konstisapp/lib
Hot swapped changes, activity restarted
D/BASE_FRAGMENT: Activity should have been started here
D/BASE_FRAGMENT: Activity should have been started here

这是我的 AndroidManifest.xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="de.coding.mb.konstisapp">

    <uses-feature
        android:name="android.hardware.camera"
        android:required="false"/>

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="18"/>
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".activities.GreatingsActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".activities.DealSelectionActivity"
            android:label="@string/title_activity_deal_selection"
            android:parentActivityName=".activities.GreatingsActivity"
            android:theme="@style/AppTheme.NoActionBar">
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="de.coding.mb.konstisapp.activities.GreatingsActivity"/>
        </activity>
        <activity
            android:name=".activities.DealCreationActivity"
            android:label="@string/title_activity_activity_deal_creation"
            android:parentActivityName=".activities.DealSelectionActivity"
            android:theme="@style/AppTheme.NoActionBar">
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="de.coding.mb.konstisapp.activities.DealSelectionActivity"/>
        </activity>
        <activity android:name=".activities.DealView"
                  android:label="@string/title_activity_deal_view"
                  android:parentActivityName=".activities.DealSelectionActivity"
                  android:theme="@style/AppTheme.NoActionBar">
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="de.coding.mb.konstisapp.activities.DealSelectionActivity">

            </meta-data>
        </activity>
</manifest>

【问题讨论】:

您是否在清单文件中添加了活动..? 你能展示你的logcat吗? getContext() 使用这个 活动被添加到 Manifest.xml 中。在片段中调用 getContext() 表单不起作用 我建议在您的片段中使用接口回调 【参考方案1】:

由于无法从 Fragment 中启动新 Activity,您可以尝试将代码迁移到托管 Activity。一种干净且可重用的方法是在新文件中创建一个接口。

public interface myInterface 
    public void startMyIntent(Intent i);

然后,在 Activity 类中实现这个接口,托管你的 Fragment

public class hostingActivity extends AppCompatActivity implements myInterface 
    @Override
    public void startMyIntent(Intent i) 
        startActivity(i);
    

在你的 Fragment 的onItemClickListener,你可以这样称呼它

_dealList.setOnItemClickListener(new AdapterView.OnItemClickListener()
    
        @Override
        public void onItemClick(AdapterView<?> parent, View v, int position, long id)
        
            Activity parentActivity = getActivity();
            Intent in = new Intent(parentActivity, DealView.class);
            in.putExtra("deal", position);
            in.putExtra("city", _citySearchBar.getText());
            ((myInterface)parentActivity).startMyIntent(in);
            Log.d("BASE_FRAGMENT", "Activity should have been started here");
        
    );

【讨论】:

非常感谢!不知道为什么其他方法不起作用,但这样做了。 @Timbo 不客气!除了工作之外,这似乎是片段做“活动的东西”的更可取的解决方案。也许这个约定是从像你这样的问题中出现的;) @Timbo 当我再次查看这个答案时,我决定将对父 Activity 的引用保存在局部变量中,因为它需要两次。在这种情况下,这并不是真正必要的,但在我看来这是更好的做法。【参考方案2】:

在 Fragment 内部,您不能只使用 startActivity() 你必须使用getActivity().startActivity(in)

_dealList.setOnItemClickListener(new AdapterView.OnItemClickListener()
    
        @Override
        public void onItemClick(AdapterView<?> parent, View v, int position, long id)
        
            Intent in = new Intent(getActivity(), DealView.class);
            in.putExtra("deal", position);
            in.putExtra("city", _citySearchBar.getText());
            getActivity().startActivity(in);
            Log.d("BASE_FRAGMENT", "Activity should have been started here");
        
    );

另见How do I start an activity from within a Fragment?

【讨论】:

我认为这是正确的答案。 OP 应该检查一下。 刚刚检查过。这里也没有任何事情发生。我也看过这个帖子,昨天试过了【参考方案3】:

更改代码

_dealList.setOnItemClickListener(new AdapterView.OnItemClickListener()
        
           @Override
            public void onItemClick(AdapterView<?> parent, View v, int position, long id)
            
                Intent in = new Intent(v.getContext(), DealView.class);
                in.putExtra("deal", position);
                in.putExtra("city", _citySearchBar.getText());
                startActivity(in);
                Log.d("BASE_FRAGMENT", "Activity should have been started here");
            
        );
    

【讨论】:

这也不起作用:(我不知道为什么它不会启动活动。v.getContext() 和 getActivity() 也返回相同的引用【参考方案4】:

在 intent.setFlags(...) 方法中使用 FLAG_ACTIVITY_NEW_TASK。

_dealList.setOnItemClickListener(new AdapterView.OnItemClickListener()
    
       @Override
        public void onItemClick(AdapterView<?> parent, View v, int position, long id)
        
            Intent in = new Intent(v.getContext(), DealView.class);
            in.putExtra("deal", position);
            in.putExtra("city", _citySearchBar.getText());
            in.setFlag(Acitvity.FLAG_ACTIVITY_NEW_TASK);
            getActivity().startActivity(in);
            Log.d("BASE_FRAGMENT", "Activity should have been started here");
        
    );

【讨论】:

这个标志只影响启动新活动的处理如果它被启动。

以上是关于Intent 不会从 Fragment 启动 Activity的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据从 Intent 传递到 Fragment

android activity 怎么跳fragment

activity和Task 有关的 Intent启动方式结合intent.setFlags()

如何在一个fragment中更新另一个fragment

调用相机应用程序(权限拒绝:启动 Intent )

activity怎么跳转到fragment