21

Đây là mã cho số Fragment cơ bản có chứa WebView.
WebFragment.java
WebView tải lại khi Fragment trong ViewPager được giữ lại dưới dạng BackStack

public class WebFragment extends Fragment { 
String TAG = "WebFragment"; 
private WebView webView; 
private String currentUrl = "http://www.google.com"; 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
    return inflater.inflate(R.layout.webview_layout, null); 
} 

@Override 
public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 
    webView = (WebView) getView().findViewById(R.id.helloWebview); 
    initWebView(); 
    webView.loadUrl(currentUrl); 
} 

@SuppressLint("SetJavaScriptEnabled") 
private void initWebView() { 
    webView.getSettings().setJavaScriptEnabled(true); 
    webView.addJavascriptInterface(new JavaScriptInterface(), "HTMLOUT"); 
    webView.setWebViewClient(new WebViewClient() { 
     @Override 
     public void onPageStarted(WebView view, String url, Bitmap favicon) { 
      Log.e(TAG, "Loding..."); 
      super.onPageStarted(view, url, favicon); 
     } 
    }); 
} 

class JavaScriptInterface { 
    public void showHTML(String html) { 
    } 
} 
} 

tôi có 2 mảnh cơ bản hơn cũng (mà không có WebView). Sau đó, tôi đặt tất cả 3 Fragments này vào số ViewPager (WebFragment, Fragment1Fragment2 tương ứng) sử dụng FragmentAdapter. Và tôi đã thêm android:configChanges="orientation|screenSize" vào AndroidManifest.xml (Vì vậy, WebView sẽ không được thực hiện trên thay đổi cấu hình).
Bây giờ vấn đề của tôi là, Trong khi chạy ứng dụng tôi đã thay đổi trang thứ nhất (WebFragmet) của ViewPager thành trang thứ hai (Fragment1) và một lần nữa tôi trở lại trang đầu tiên. Vì vậy, không có vấn đề WebFragment là như nó được.

Bây giờ một lần nữa tôi đã thay đổi ViewPager như thế này WebFragment ->Fragment1 ->Fragment2 và trở lại trang đầu tiên bằng cách đảo ngược hướng của hành động trên. Nhưng vào thời điểm đó tôi thấy số WebView ở số WebFragment đang tải lại.

Và một vấn đề nữa, bất cứ khi nào WebView bắt đầu tải, tôi có thể thấy 2 mục nhập nhật ký như thế nào.

WebFragment Loading... 
WebFragment Loading... 

Vì vậy, câu hỏi của tôi là:
1) Làm thế nào tôi có thể ngăn chặn WebView nạp lại khi WebFragment được giữ lại từ BackStack?
2) Tại sao ở đây WebView tải hai lần?

Chỉ cần xem câu hỏi này và giúp tôi (Prevent WebView reloads in FragmentPagerAdapter?).

Trả lời

26

Trong hoạt động chính của bạn, nơi bạn đã xác định ViewPager

sau khi tuyên bố ViewPager như dòng này: ViewPager viewpager = (ViewPager) findViewById(R.id.pager);

thêm dòng này:

viewpager.setOffscreenPageLimit(2); 

này sẽ ngăn chặn đoạn từ tái tạo tối đa vuốt hai màn hình, vì vậy khi bạn quay trở lại từ trang thứ 3 đến trang thứ nhất trong chế độ xem, chế độ xem web của bạn sẽ không tải lại.

+0

Chắc chắn đây là câu trả lời đúng. – Wamasa

+0

@Chirag Shah thực sự tôi biết điều này ('viewpager.setOffscreenPageLimit (2);') nhưng nếu tôi có 5 hoặc nhiều hơn 'Fragments' trong' ViewPager' của tôi với 'WebView' nếu tôi đặt' viewpager.setOffscreenPageLimit (5+); ', Nó sẽ là một lựa chọn tồi, rigth? Những gì bạn nói? –

+0

Bạn có thể trả lời cho câu hỏi thứ 2 của tôi không? –

2

Tốt cho các đoạn sử dụng như thế này.

A extends Fragment 

{ 

    static WebView w; 

    View v; 

    private Handler handler = new Handler(){ 

    @Override 
    public void handleMessage(Message message) { 

     switch (message.what) { 
      case 1:{ 
       webViewGoBack(); 
      }break; 
     } 
    } 

    private void webViewGoBack() { 
     w.goBack(); 

     // TODO Auto-generated method stub 

    } 
}; 

@Override 

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ 

v = inflater.inflate(R.layout.webs, container, false); 

w=(WebView)v.findViewById(R.id.webView1); 

//w.loadUrl(""); 

} 

w.setOnKeyListener(new OnKeyListener(){ 

@Override 

public boolean onKey(View v, int keyCode, KeyEvent event) { 

      // TODO Auto-generated method stub 
    if((keyCode==KeyEvent.KEYCODE_BACK)&& w.canGoBack()) 

      { 

       handler.sendEmptyMessage(1); 

       return true; 

      } 
      return false; 
     } 

    }); 
4

Đây là trường hợp điển hình là nạn nhân của việc sửa lỗi dễ dàng ghi đè android:configChanges để khắc phục sự cố. Thật không may có nhiều lý do tại sao một thay đổi cấu hình sẽ xảy ra. Vì vậy, chỉ cần bắt cho một thay đổi kích thước màn hình sẽ bỏ lỡ rất nhiều trong số họ ... như bạn đã phát hiện ra.

Trước tiên, hãy xóa hoàn toàn android:configChanges. Sau đó, thêm phần sau vào đoạn WebView của bạn.

protected void onSaveInstanceState(Bundle outState) { 
    webView.saveState(outState); 
} 

Điều chỉnh phương pháp đoạn WebView của bạn onActivityCreated để bao gồm những điều sau đây:

public void onActivityCreated(Bundle savedInstanceState) { 
    webView = (WebView) getView().findViewById(R.id.helloWebview); 
    initWebView(); 

    if (savedInstanceState != null) 
     webView.restoreState(savedInstanceState); 
    else 
     webView.loadUrl(currentUrl); 

}

Điều đó sẽ giúp bạn đi đúng hướng. Lưu ý, gọi saveState() của WebView sẽ không lưu dữ liệu hiển thị. Ví dụ: thẻ đầu vào sẽ không duy trì được đầu vào của người dùng. Bạn sẽ cần phải phân tích cú pháp thông qua trang web theo cách thủ công để duy trì dữ liệu đó. Tùy thuộc vào những gì bạn đang sử dụng WebView cho, điều này sẽ là một nỗi đau lớn.

Các vấn đề liên quan