WebView片段内的OnKeyDown

Mab*_*jik 5 android webview android-fragments

我做了一个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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Xav*_*ler 8

它可能会奏效,但这不是一个好主意.如果你没有Fragment正确处理它或者你的代码中的某个地方对它的生命周期有点粗心,它很可能会导致崩溃.但有一个简单的方法来解决这个问题.而不是使用静态方法,在实例本身上保存实例和调用方法.这样,您就可以检查是否实例为null,如果没有,则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);
    }
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的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();  
        }  
    }
}
Run Code Online (Sandbox Code Playgroud)

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

通常这种方法要好得多.特别是从架构的角度,因为你不直接与互动WebViewActivity.该WebView不会有什么做的Activity,它是对执行工作的一部分BrowserFragment,因此在Activity不应该知道,甚至有一个WebView.如何调用goBack()canGoBack()实现调用或者他们究竟做了什么是没有兴趣的Activity.在 Activity刚告诉BrowserFragment"我要回去",而BrowserFragment做的工作.这样可以更好地分离职责,使代码更易读,更清晰,更易于维护.

编辑:

另外我不知道一个SingleFragmentActivity但通常是任何Activity实现onBackPressed()方法.您不必重写onKeyDown()以捕获后退键事件.你可以这样做:

@Override
public void onBackPressed() {
    if (this.browserFragment != null && this.browserFragment.canGoBack()) {
        this.browserFragment.goBack();
    } else {  
        // The back key event only counts if we execute super.onBackPressed();
        super.onBackPressed();
    }
}
Run Code Online (Sandbox Code Playgroud)

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