我制作了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);
}
}
答案 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
进行互动。 Activity
与WebView
没有任何关系,它是Activity
实施的一部分,因此BrowserFragment
不应该知道那里甚至是Activity
。 WebView
对goBack()
或canGoBack()
的调用是如何实施的,或者他们确实做了什么。 Activity
只是告诉Activity
"我想回去"并且BrowserFragment
完成了工作。这样可以更好地分离职责,使代码更具可读性,更清晰,更易于维护。
修改强>
此外,我不知道BrowserFragment
但通常是SingleFragmentActivity
实施Activity
方法。您不必覆盖onBackPressed()
来捕获后退键事件。你可以这样做:
onKeyDown()
如果您有任何其他问题,请随时提出!