片段分离后显示Toast消息?

时间:2018-03-27 14:37:44

标签: android toast

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

然而,即便如此,有可能举办Toast秀吗?当导航器上单击一个项目时,我基本上有这个代码。

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

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

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

感谢任何帮助。

更新(03/28/2018)

我尝试使用监听器,似乎有效。

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

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);
    }
}

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

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中:

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();
    }

}

1 个答案:

答案 0 :(得分:1)

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

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

我会说您正在接收空指针,因为您不再拥有上下文。

可能的解决方案是:

1-将应用程序声明为单例,然后您可以使用MyApplication.getInstance()并将其用作Toast消息的上下文。检查此link以了解如何创建此单例。此外,recommended使用applicationContext而不是toast消息的活动

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

编辑1:

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

setRetainInstance(true);

您可能需要阅读此post

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

PS:对不起,迟到的回答,我正在度假:P。

相关问题