Android OnKeyDown内部WebView片段
我制作了一个Android OnKeyDown内部WebView片段,android,android-fragments,webview,Android,Android Fragments,Webview,我制作了一个片段,其中包含一个WebView,我想定义一个onKeyDown(),从一个网页返回到上一个网页。我这样做了,但对我来说最奇怪的是从我的Fragment类到我的Activity类共享一个WebView变量,因为我无法在Fragment中定义onKeyDown()。所以我定义了一个get方法,并将其设置为静态。但我想知道这是否真的是一个错误,我的应用程序在某些情况下可能会严重崩溃 我的片段代码: public class BrowserFragment extends Fragment
片段
,其中包含一个WebView
,我想定义一个onKeyDown()
,从一个网页返回到上一个网页。我这样做了,但对我来说最奇怪的是从我的Fragment
类到我的Activity
类共享一个WebView
变量,因为我无法在Fragment
中定义onKeyDown()
。所以我定义了一个get方法,并将其设置为静态。但我想知道这是否真的是一个错误,我的应用程序在某些情况下可能会严重崩溃
我的片段
代码:
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;
}
}
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);
}
}
和我的活动
代码:
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;
}
}
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);
}
}
这可能行得通,但不是个好主意。如果您没有正确处理
片段
,或者代码中的某个地方对其生命周期有点粗心,那么它很可能会导致崩溃。但是有一个简单的方法可以解决这个问题。不要使用静态方法,而是保存实例并对实例本身调用方法。通过这种方式,您可以检查实例是否为null,如果不是,则片段可以处理对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
实例被保存,然后在BrowserFragment
本身上调用goBack()
或canGoBack()
等方法。当然,您必须在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();
}
}
}
我对你的代码做了一些额外的改进。首先,我添加了空检查以防止任何可能的NullPointerException
,其次,建议始终使用静态工厂方法来创建片段的新实例。这就是我添加到BrowserFragment
的静态newInstance()
方法。这样做的好处是,您可以实现一种方法,该方法负责为您设置BrowserFragment
,而不管您在哪里使用它。您可以向newInstance()
方法添加参数,以将一些值传递给BrowserFragment
或添加一些必需的侦听器等,但由于您没有将任何值传递给BrowserFragment
方法,因此newInstance()
方法仍然是空的。尽管如此,最好始终使用此类工厂方法,即使它们只调用newbrowserfragment()
一般来说,这种方法要好得多。尤其是从体系结构的角度来看,因为您不直接与活动中的WebView
交互。WebView
与Activity
无关,它是BrowserFragment
实现的一部分,因此Activity
不应该知道甚至存在WebView
。对goBack()
或canGoBack()
的调用是如何实现的,或者它们到底做了什么,这与活动
无关。Activity
只告诉BrowserFragment
“我想回去”,而BrowserFragment
完成了这项工作。这将更好地分离责任,并使代码更可读、更清晰和更易于维护
编辑:
我也不知道有什么SingleFragmentActivity
,但通常任何活动都会实现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();
}
}
如果您有任何其他问题,请随时提问 哦!!非常感谢您的辛勤工作和解释!这正是我想要实现的,但不知道如何实现(尤其是如何使片段将工作作为一项活动)。我的SIngleFragment活动只包含创建片段、开始事务和添加到容器的代码。非常感谢。现在我将仔细考虑一下您的整个实现=),顺便说一句,您可能知道,我在片段中添加了WebView,这样活动生命周期就不会影响页面表示。例如,我从纵向模式改为横向模式,我不希望我的应用程序再次下载起始页。我应该在saveInstanceState中保存一些东西,但是我应该保存什么呢?谢谢,+1提供了清晰的代码和很好的解释。这对我来说非常有效!我只有一个问题,当我在安卓系统中有一个菜单打开我的网络视图中的链接时,我该如何处理?当我点击webview内的链接时效果很好,但当我点击菜单“配置文件”,然后点击另一个菜单并按back时,它就不起作用了。。。你知道我该怎么修吗?:)