草庐IT

关于 android:即使在 Fragment 分离后也显示 Toast 消息?

codeneng 2023-03-28 原文

Show Toast message even after Fragment has been detached?

我的应用程序使用带有几个菜单项的导航抽屉,这些菜单项基本上可以打开不同的片段。每个片段可以运行一个 AsyncTask,之后显示 Toast 消息。但是,当用户在另一个片段正在运行时尝试打开一个片段时,我会收到一个空指针错误,这是可以理解的,因为原始片段已被分离。

但是,即使在那时也有可能举行 Toast 表演吗?当在导航器上单击项目时,我基本上有此代码。

1
2
3
4
5
6
public void setFragment(Fragment fragment) {
    getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.content, fragment)
            .commit();
}

然后在片段上只是一个简单的 asynctask,它在 PostExecute 上显示 Toast 消息。

1
Toast.makeText(getContext(), t.getLocalizedMessage(), Toast.LENGTH_LONG).show();

感谢任何帮助。

更新(2018 年 3 月 28 日)

我尝试使用监听器,它似乎工作。

我基本上有一个 BaseFragment,我的所有片段都在其中扩展。我只是在其中添加了一个回调。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class BaseFragment extends Fragment {

    private OnToast callback;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            callback = (BaseFragment.OnToast) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString() +" must implement OnAuthenticateListener");
        }
    }

    public OnToast getCallback() {
        return callback;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
        setHasOptionsMenu(true);
    }

    public interface OnToast {
        void toast(String message);
    }
}

在我的实际片段中,我有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class JailsFragment extends BaseFragment {

    private List<Jail> jailList = new ArrayList<>();

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setTitle("Jails");
        setAdapter(new JailAdapter());

        if (savedInstanceState == null) {
            onSwipeRefresh();
        }

    }

    @Override
    public void onSwipeRefresh() {
        super.onSwipeRefresh();
        setRefreshing(true);
        jailList.clear();
        FreeNAS.getInstance().getJails().getJails(new Callback<List<Jail>>() {
            @Override
            public void onResponse(Call<List<Jail>> call, Response<List<Jail>> response) {
                if (response.code() == 200) {
                    jailList.addAll(response.body());
                    notifyDatasetChanged();
                } else {
                    //Toast.makeText(getContext(), response.message(), Toast.LENGTH_LONG).show();
                    getCallback().toast(response.message());
                }
                setRefreshing(false);
            }

            @Override
            public void onFailure(Call<List<Jail>> call, Throwable t) {
                //Toast.makeText(getContext(), t.getLocalizedMessage(), Toast.LENGTH_LONG).show();
                getCallback().toast(t.getLocalizedMessage());
                setRefreshing(false);
            }
        });
    }

}

然后在我的 MainActivity 中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, BaseFragment.OnToast {

    private SharedPreferences pref;
    private Toolbar toolbar;
    private DrawerLayout drawer;
    private ActionBarDrawerToggle toggle;
    private NavigationView navigationView;

    @Override
    public void toast(String message) {
        Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
    }

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

        pref = PreferenceManager.getDefaultSharedPreferences(this);

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        if (savedInstanceState == null) {
            setFragment(new AuthenticateFragment());
        }

    }

    @Override
    public void onBackPressed() {
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.

        final int id = item.getItemId();

        drawer.closeDrawer(GravityCompat.START);
        drawer.postDelayed(new Runnable() {
            @Override
            public void run() {

                if (id == R.id.nav_plugins) {
                    setFragment(new PluginsFragment());
                } else if (id == R.id.nav_jails) {
                    setFragment(new JailsFragment());
                } else if (id == R.id.nav_jails_configuration) {
                    setFragment(new ConfigurationFragment());
                } else if (id == R.id.nav_services) {
                    setFragment(new ServicesFragment());
                } else if (id == R.id.nav_alerts) {
                    setFragment(new AlertsFragment());
                } else if (id == R.id.nav_updates) {
                    setFragment(new UpdatesFragment());
                }
            }
        }, 300);

        return true;
    }

    public void setFragment(Fragment fragment) {
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.content, fragment)
                .commit();
    }

}

  • 我已经编辑了我的答案以考虑您的方法:)。


我假设你在这里收到了一个 nullPointer 异常

1
Toast.makeText(getContext(), t.getLocalizedMessage(), Toast.LENGTH_LONG).show();

我会说你收到空指针是因为你没有上下文了。

可能的解决方案是:

1- 将您的应用程序声明为单例,然后您可以使用 MyApplication.getInstance() 并将其用作 Toast 消息的上下文。检查此链接以了解如何创建此单例。还建议使用 applicationContext 而不是 Activity 来获取 toast 消息

据我了解 getContext() 和 getActivity() 将返回相同的对象,这是活动,因此无济于事。

编辑 1:

您提出的解决方案的问题(对 Activity 的引用,在本例中为接口)是您可能存在内存泄漏。当我说"可能有"时,是因为您在输入此行时正在做一些特别的事情:

1
setRetainInstance(true);

您可能想阅读这篇文章。

当您不再需要 Activity(假设您移动到另一个 Activity)但由于某种原因片段(对象)尚未被销毁时,将产生内存泄漏。另一个例子是与互联网的低连接,然后用户可能会离开屏幕移动到另一个屏幕,但你的片段仍然活着,所以你的活动不能被垃圾收集。这就是为什么我不推荐你的方法:).

PS:抱歉回复晚了,我正在度假:P.

  • 谢谢。似乎可以正常工作。但是,我也尝试在 Fragment 中使用侦听器,然后 Activity 将实现该侦听器并显示 Toast 消息,它似乎也可以正常工作。但是,我不确定哪种方法更好。你能建议吗。
  • @ank 这取决于您如何实现该逻辑。你能写出来让我给你我的意见吗?

有关关于 android:即使在 Fragment 分离后也显示 Toast 消息?的更多相关文章

  1. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  4. ruby-on-rails - link_to 不显示任何 rails - 2

    我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article

  5. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  6. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  7. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

    我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

  8. ruby-on-rails - 复数 for fields_for has_many 关联未显示在 View 中 - 2

    目前,Itembelongs_toCompany和has_manyItemVariants。我正在尝试使用嵌套的fields_for通过Item表单添加ItemVariant字段,但是使用:item_variants不显示该表单。只有当我使用单数时才会显示。我检查了我的关联,它们似乎是正确的,这可能与嵌套在公司下的项目有关,还是我遗漏了其他东西?提前致谢。注意:下面的代码片段中省略了不相关的代码。编辑:不知道这是否相关,但我正在使用CanCan进行身份验证。routes.rbresources:companiesdoresources:itemsenditem.rbclassItemi

  9. Ruby - 如何将消息长度表示为 2 个二进制字节 - 2

    我正在使用Ruby,我正在与一个网络端点通信,该端点在发送消息本身之前需要格式化“header”。header中的第一个字段必须是消息长度,它被定义为网络字节顺序中的2二进制字节消息长度。比如我的消息长度是1024。如何将1024表示为二进制双字节? 最佳答案 Ruby(以及Perl和Python等)中字节整理的标准工具是pack和unpack。ruby的packisinArray.您的长度应该是两个字节长,并且按网络字节顺序排列,这听起来像是n格式说明符的工作:n|Integer|16-bitunsigned,network(bi

  10. ruby-on-rails - 在 Flash 警报 Rails 3 中显示错误消息 - 2

    如果我在模型中设置验证消息validates:name,:presence=>{:message=>'Thenamecantbeblank.'}我如何让该消息显示在闪光警报中,这是我迄今为止尝试过的方法defcreate@message=Message.new(params[:message])if@message.valid?ContactMailer.send_mail(@message).deliverredirect_to(root_path,:notice=>"Thanksforyourmessage,Iwillbeintouchsoon")elseflash[:error]

随机推荐