WebView片段内的OnKeyDown

时间:2014-04-22 22:14:43

标签: android android-fragments webview

我制作了Fragment,其中包含WebView,我想定义一个onKeyDown()以从一个网页返回到上一个网页。我做到了,但对我来说最奇怪的部分是从我的WebView班级到Fragment班级分享Activity变量,因为我无法定义onKeyDown() Fragment。所以我只是定义了一个get方法并使其成为静态的。但我想知道这是不是一个真正的错误,我的应用程序在某些情况下会严重崩溃。

我的Fragment代码:

public class BrowserFragment extends Fragment {
    private static WebView webView;

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

    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
        View v = inflater.inflate(R.layout.fragment_activity, parent, false);

        getActivity().setTitle(R.string.title_rus);

        webView = (WebView) v.findViewById(R.id.webView);
        webView.setWebViewClient(new SwingBrowserClient());
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        Uri data = Uri.parse("http://www.swinginmoscow.ru/m/");
        webView.loadUrl(data.toString());

        return v;
    }

    public static WebView getWebView() {
        return webView;
    }
}

我的Activity代码:

public class MainBrowserActivity extends SingleFragmentActivity {

    @Override
    protected Fragment createFragment() {
        return new BrowserFragment();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && BrowserFragment.getWebView().canGoBack()) {
            BrowserFragment.getWebView().goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}

1 个答案:

答案 0 :(得分:8)

它可能会奏效,但这不是一个好主意。如果您没有正确处理Fragment或者代码中某处对其生命周期稍有不小心,那么很可能导致崩溃。但有一个简单的方法来解决这个问题。而不是使用静态方法,在实例本身上保存实例和调用方法。通过这种方式,您可以检查实例是否为空,如果不是Fragment可以处理对goBack()canGoBack()本身的调用:

public class MainBrowserActivity extends SingleFragmentActivity {

    BrowserFragment browserFragment = null;

    @Override
    protected Fragment createFragment() {
        this.browserFragment = BrowserFragment.newInstance();
        return this.browserFragment;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && this.browserFragment != null && this.browserFragment.canGoBack()) {
            this.browserFragment.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}

如您所见,BrowserFragment实例已保存,然后在goBack()本身上调用canGoBack()BrowserFragment等方法。当然,您必须在BrowserFragment中实现这些方法,但这不应该是一个问题:

public class BrowserFragment extends Fragment {

    public static BrowserFragment newInstance() {
        BrowserFragment fragment = new BrowserFragment();
        return fragment;
    }

    private WebView webView;

    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
        View v = inflater.inflate(R.layout.fragment_activity, parent, false);

        getActivity().setTitle(R.string.title_rus);

        webView = (WebView) v.findViewById(R.id.webView);
        webView.setWebViewClient(new SwingBrowserClient());
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        Uri data = Uri.parse("http://www.swinginmoscow.ru/m/");
        webView.loadUrl(data.toString());
        return v;
    }

    public boolean canGoBack() {
        return this.webView != null && this.webView.canGoBack();
    }

    public void goBack() {
        if(this.webView != null) {
            this.webView.goBack();  
        }  
    }
}

我对您的代码进行了一些额外的改进。首先,我添加了空检查以防止任何可能的NullPointerExceptions,其次建议始终使用静态工厂方法来创建Fragments的新实例。这就是我添加到newInstance()的静态BrowserFragment方法。这样做的好处是,您可以实现一种方法,无论您在何处使用它,都可以为您设置BrowserFragment。您可以向newInstance()方法添加参数以将一些值传递给BrowserFragment或添加一些必需的侦听器等,但因为您没有将任何值传递给BrowserFragment {{ 1}}方法仍然很空。尽管如此,最好始终使用这种工厂方法,即使他们只调用newInstance()

通常这种方法要好得多。特别是从架构的角度来看,因为您不能直接与new BrowserFragment()中的WebView进行互动。 ActivityWebView没有任何关系,它是Activity实施的一部分,因此BrowserFragment不应该知道那里甚至是ActivityWebViewgoBack()canGoBack()的调用是如何实施的,或者他们确实做了什么。 Activity只是告诉Activity"我想回去"并且BrowserFragment完成了工作。这样可以更好地分离职责,使代码更具可读性,更清晰,更易于维护。

修改

此外,我不知道BrowserFragment但通常是SingleFragmentActivity实施Activity方法。您不必覆盖onBackPressed()来捕获后退键事件。你可以这样做:

onKeyDown()

如果您有任何其他问题,请随时提出!