Реализация двухстороннего связывания данных WebView с использованием MVVM в Kotlin - PullRequest
0 голосов
/ 22 января 2020

Я пытаюсь реализовать MVVM во всех моих приложениях, и я очень новичок в этом, поэтому я хочу загрузить веб-просмотр через мою ViewModel, но я не знаю лучший способ, как это сделать, если также есть индикатор выполнения, который отображается, когда загружается мое веб-представление.

Вот код:

    class NewWebViewFragment : Fragment() {

    private lateinit var viewModel: NewWebViewViewModel

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

        val binding: FragmentWebViewBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_web_view, container, false)

        val webViewModelo = ViewModelProviders.of(this).get(NewWebViewViewModel::class.java)

        binding.webViewModel = webViewModelo
        binding.lifecycleOwner = this


        return binding.root
    }

}

Теперь мой ViewModel:

class NewWebViewViewModel : ViewModel() {

//Implement in MVVM

private fun showWebView(webView: WebView, progressBar: ProgressBar) {

        webView.webViewClient = WebViewClient()
        webView.webChromeClient = WebChromeClient()

        val webSettings = webView.settings
        webSettings.javaScriptEnabled = true

        webView.loadUrl("https://brand.randombrand.com/en/")

        webView.webViewClient = object : WebViewClient() {
            override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                progressBar.visibility = View.VISIBLE
                super.onPageStarted(view, url, favicon)
            }

            override fun onPageFinished(view: WebView?, url: String?) {
                progressBar.visibility = View.GONE
                super.onPageFinished(view, url)
            }
        }
    }
}

и мой XML:

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">


    <data>
        <variable
            name="webViewModel"
            type="com.example.navigations.viewmodel.webview.NewWebViewViewModel" />
    </data>

    <FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".fragments.WebViewFragment">


    <!-- TODO: Update blank fragment layout -->
        <WebView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/webView"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">


    </WebView>

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/progressBar"
        android:layout_gravity="center"/>


    </FrameLayout>
</layout>

Ошибка, которую я получаю, nullpointerexception, потому что веб-просмотр, который я передаю, является нулевым. Есть мысли о том, как лучше всего это реализовать?

Ответы [ 3 ]

1 голос
/ 22 января 2020

Я думаю, что лучшим вариантом для вас было бы создать Binding Adapter, который будет выглядеть следующим образом:

@BindingAdapter("loadUrl")
fun WebView.setUrl(url: String) {
    this.loadUrl(url)
}

В вашей ViewModel вы можете получать данные либо через аргументы Fragment (возможно, если они получены из другой фрагмент) или просто измените их из ViewModel.

В виртуальной машине данные будут являться URL-адресом для загрузки, например, val webViewUrl = MutableLiveData<String>().apply{ value = "initial url to be loaded .com" }.

И в вашем xml:

<WebView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/webView"
        app:loadUrl="@{viewModel.webViewUrl}"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">

И да, вы никогда не должны делать вещи пользовательского интерфейса во ViewModel, например создавать экземпляры WebView или что-то в этом роде.

1 голос
/ 22 января 2020

Вы не можете использовать webview в viewmodel

смотреть https://developer.android.com/topic/libraries/data-binding/binding-adapters.html

Правила MVVM

Номер правила One : В представлении не должно быть логики c, совсем нет! Даже не простое условие. Все логи c для представления происходят во ViewModel.

Правило номер два : В ответ на события представление ничего не делает, кроме уведомления модели представления путем вызова метода. Представление не передает никакие связанные с представлением классы для просмотра модели.

Правило номер три : ViewModel использует живые данные в качестве основного способа связи для просмотра!

Один из Преимущества MVVM в том, что ViewModel не должен ничего знать о View и не имеет ссылок на классы View! Вместо этого он использует парадигму реактивного программирования, поэтому View по-прежнему может наблюдать данные и получать уведомления об изменениях.

Правило номер четыре : View может вызывать модель представления всякий раз, когда ему что-то нужно. ViewModel может предоставить вспомогательные методы для представления.

0 голосов
/ 23 января 2020

Я нашел решение для загрузки webView. Вот что я сделал:

 import android.webkit.WebView
import androidx.databinding.BindingAdapter

object Utilities {

    @BindingAdapter("loadUrl")
    @JvmStatic
    fun WebView.setUrl(url: String) {
        this.loadUrl(url)
    }
}

1 # создал объект для Utils

<WebView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/webView"
            app:loadUrl="@{webViewModel.webViewUrl}"
            app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
            >

2 # Обновлен XML, теперь он выглядит

3 # val webViewUrl = MutableLiveData (). apply {value = "https://google.com/en/"}

добавил это в мой класс ViewModel

Спасибо за комментарии, ребята

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...