I'm making a webview in android app and want to implement swipe to refresh gesture. but can't get through due to one error.
swipe.setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener())
what parameter should be pass to this function??
Here is my mainactivity.kt file
var mWebView : WebView? = null
abstract class MainActivity : AppCompatActivity() {
lateinit var swipe:SwipeRefreshLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
swipe = findViewById(R.id.swipe) as SwipeRefreshLayout
**swipe.setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener())**
run {
val onRefresh:Unit
run({ Loadweb() })
}
}
fun Loadweb() {
mWebView = findViewById<View>(R.id.webView) as WebView
mWebView!!.webViewClient = object : WebViewClient () {
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
view?.loadUrl(url)
return true
}
}
val webSettings = mWebView!!.getSettings()
webSettings.setJavaScriptEnabled(true)
webSettings.setUseWideViewPort(true)
mWebView!!.loadUrl("http://allnumber.info/")
}
override fun onBackPressed() {
if (mWebView!!.canGoBack()){
mWebView!!.goBack()
}
else {
super.onBackPressed()
}
}}
This is the error message
No value passed for parameter 'function'
Try this code
private lateinit var mHandler: Handler
private lateinit var mRunnable:Runnable
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Initialize the handler instance
mHandler = Handler()
swipe = findViewById(R.id.swipe) as SwipeRefreshLayout
swipe.setOnRefreshListener{
mRunnable = Runnable {
Loadweb()
swipe_refresh_layout.isRefreshing = false
}
// Execute the task after specified time
mHandler.postDelayed(
mRunnable,
(randomInRange(1,5)*1000).toLong() // Delay 1 to 5 seconds
)
}
}
}
i think you should pass
(object:SwipeRefreshLayout.OnRefreshListener(){
//override methods
})
Related
I have an activity where I setup an animated AnimatedVector on an ImageView then I am loading an url in a WebView, everythings good right here.
The issue is in onPageStarted webview client callback, I got a crash because binding.loader.drawable return null so the cast is impossible.
I can't figure it out why the drawable is null here !
Second issue is (if i comment the line in onPageStarted) in onPageFinished, the two visibility of my views I try to set does nothing at all, they are still visibles.
Spoiler : Of course the app crash right after when trying to get the drawable and cast it
Have you already face this issue ?
class ViewRecipeActivity : AppCompatActivity() {
private val binding by viewBinding(ActivityViewRecipeBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
setupUI()
}
//region setup UI
private fun setupUI() {
setUpLoader()
setupWebView()
}
private fun setUpLoader() {
with(binding.loader) {
val drawable = AnimatedVectorDrawableCompat.create(this#ViewRecipeActivity, R.drawable.animated_loader)
setImageDrawable(drawable)
}
}
private fun setupWebView() {
val client = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
(binding.loader.drawable as Animatable).start() //Crash here because drawable is null
}
override fun onPageFinished(view: WebView?, url: String?) {
binding.loader.visibility = View.GONE
binding.loaderBackground.visibility = View.GONE
(binding.loader.drawable as Animatable).stop()
}
}
with(binding.recipeView) {
webViewClient = client
}
val recipeUrl = intent.extras?.getString(RECIPE_URL_EXTRA)
if(recipeUrl == null) {
Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show()
} else {
binding.recipeView.loadUrl(recipeUrl)
}
}
//endregion
companion object {
const val RECIPE_URL_EXTRA = "recipe_url_extra"
}
}
I have a fragment in my project:
private const val TAG = "PhotoGalleryFragment"
class PhotoGalleryFragment: Fragment() {
private lateinit var photoRecyclerView: RecyclerView
private lateinit var photoGalleryViewModel: PhotoGalleryViewModel
private lateinit var thumbnailDownloader: ThumbnailDownloader<PhotoHolder>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
retainInstance = true
photoGalleryViewModel = ViewModelProvider(this).get(PhotoGalleryViewModel::class.java)
thumbnailDownloader = ThumbnailDownloader()
lifecycle.addObserver(thumbnailDownloader)
}
override fun onCreateView (inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View?
{
val view = inflater.inflate(R.layout.fragment_photo_gallery, container, false)
photoRecyclerView = view.findViewById(R.id.photo_recycler_view)
photoRecyclerView.layoutManager = GridLayoutManager(context, 3)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
photoGalleryViewModel.galleryItemLiveData.observe(viewLifecycleOwner,
Observer { galleryItems ->
photoRecyclerView.adapter = PhotoAdapter(galleryItems)
}
)
}
private class PhotoHolder(imageView: ImageView) : RecyclerView.ViewHolder(imageView) {
val bindDrawable: (Drawable) -> Unit = imageView::setImageDrawable
}
private inner class PhotoAdapter(private val galleryItems: List<GalleryItem>):
RecyclerView.Adapter<PhotoHolder>()
{
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PhotoHolder
{
val view = layoutInflater.inflate(R.layout.list_item_gallery, parent, false)
as ImageView
return PhotoHolder(view)
}
override fun getItemCount(): Int = galleryItems.size
override fun onBindViewHolder(holder: PhotoHolder, position: Int) {
val galleryItem = galleryItems[position]
val placeholder: Drawable = ContextCompat.getDrawable(requireContext(),
R.drawable.bill_up_close) ?: ColorDrawable()
holder.bindDrawable(placeholder)
thumbnailDownloader.queueThumbnail(holder, galleryItem.url)
}
}
override fun onDestroy() {
super.onDestroy()
lifecycle.removeObserver(thumbnailDownloader)
}
companion object {
fun newInstance() = PhotoGalleryFragment()
}
}
And also I have a class for download thumbnails from Flickr in background thread:
private const val TAG = "ThumbnailDownloader"
private const val MESSAGE_DOWNLOAD = 0
class ThumbnailDownloader<in T> : HandlerThread(TAG), LifecycleObserver {
private var hasQuit = false
private lateinit var requestHandler: Handler
private val requestMap = ConcurrentHashMap<T, String>()
private val flickr = Flickr(ApiSingleton.get().flickr)
override fun quit(): Boolean {
hasQuit = true
return super.quit()
}
fun queueThumbnail (target: T, url: String) {
Log.i (TAG, "Got a url: $url")
requestMap[target] = url
requestHandler = Handler()
requestHandler.obtainMessage(MESSAGE_DOWNLOAD, target).sendToTarget()
}
#Suppress("UNCHECKED_CAST")
#SuppressLint("HandlerLeak")
override fun onLooperPrepared() {
requestHandler = object : Handler() {
override fun handleMessage(msg: Message) {
if (msg.what == MESSAGE_DOWNLOAD) {
val target = msg.obj as T
Log.i (TAG, "Got a request for URL: ${requestMap[target]}")
handleRequest(target)
}
}
}
}
private fun handleRequest(target: T) {
val url = requestMap[target] ?: return
val bitmap = flickr.fetchPhoto(url) ?: return
}
#OnLifecycleEvent (Lifecycle.Event.ON_CREATE)
fun setup() {
Log.i (TAG,"Starting background thread")
}
#OnLifecycleEvent (Lifecycle.Event.ON_DESTROY)
fun tearDown() {
Log.i (TAG, "Destroying background thread")
}
}
When I start my program, I have following logs:
I/ThumbnailDownloader: Starting background thread
I/ThumbnailDownloader: Got a url: https://live.staticflickr.com/65535/51311768062_a2d5c73f65_m.jpg
...
I/ThumbnailDownloader: Got a url: https://live.staticflickr.com/65535/51312058978_199964de5a_m.jpg
But I planned to have another logs:
I/ThumbnailDownloader: Starting background thread
I/ThumbnailDownloader: Got a url: https://live.staticflickr.com/65535/51311768062_a2d5c73f65_m.jpg
I/ThumbnailDownloader: Got a request for URL: https://live.staticflickr.com/65535/51311768062_a2d5c73f65_m.jpg
...
I/ThumbnailDownloader: Got a url: https://live.staticflickr.com/65535/51312058978_199964de5a_m.jpg
I/ThumbnailDownloader: Got a request for URL: https://live.staticflickr.com/65535/51312058978_199964de5a_m.jpg
I.e. code of the override fun handleMessage(msg: Message) doesn't performed.
Maybe this is because of line requestHandler = Handler(), where Handler() is crossed out,
Android Studio tells that it is deprecated.
What I need to do to run handleMessage code? Maybe I need to do something with Looper in
background thread, I don't know. Thanks for your answers!
I forgut :
to add looper to my Handler() constructor in onLooperPrepared()
to add start() in fun setup(), and quit() to fun tearDown()
and the code line requestHandler = Handler() was excess.
I guessed all this after I watch a small movie with simple explanation what is going on with HandlerThread, Handler and Looper.
Problem is closed.
Declaration of variables
private lateinit var wayoJob: Job
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + wayoJob
Function
#InternalCoroutinesApi
private fun startRepeatingJob(timeInterval: Long): Job {
return CoroutineScope(Dispatchers.Default).launch {
while (NonCancellable.isActive) {
Log.i("API", "UPDATE")
delay(timeInterval)
}
}
}
In the Start Button
wayoJob = startRepeatingJob(5000L)
In Button end and onDestroy()
wayoJob.cancel()
When I click the End button it returns an error:
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property wayoJob has not been initialized
Is there any way around this?
I have to do a function that starts executing every few seconds when I press a button and will end when I click another button.
EDIT:
I could try something like this with my own shouldBeActive value and run when I need to, but that's not how it should be
var shouldBeActive = false
#InternalCoroutinesApi
private fun startRepeatingJob(timeInterval: Long): Job {
return CoroutineScope(Dispatchers.Default).launch {
while (NonCancellable.isActive && shouldBeActive) {
Log.i("API", "UPDATE")
delay(timeInterval)
}
}
}
I found a solution.
I have an Activity reload and the object resets
The solution is to insert it like below. This solution ensures that no second object is created in the meantime
companion object {
private lateinit var wayoJob: Job
}
Sample whole class:
class StartActivity : AppCompatActivity(), CoroutineScope {
companion object {
private lateinit var wayoJob: Job
}
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + wayoJob
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_start)
}
#InternalCoroutinesApi
private fun startRepeatingJob(timeInterval: Long): Job {
return CoroutineScope(Dispatchers.Default).launch {
while (NonCancellable.isActive) {
Log.i("API", "UPDATE")
delay(timeInterval)
}
}
}
#InternalCoroutinesApi
fun endBtnOnClick(view: View?) {
wayoJob.cancel()
}
#InternalCoroutinesApi
fun startBtnOnClick(view: View?) {
wayoJob = startRepeatingJob(5000L)
}
override fun onDestroy() {
super.onDestroy()
wayoJob.cancel()
}
}
I'm trying to pass the runOnUiThread method to my ServerThread:
class MainActivity : AppCompatActivity() {
private lateinit var serverThread: Thread
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// stuff...
this.serverThread = Thread(ServerThread(runOnUiThread))
this.serverThread.start()
}
}
class ServerThread(val runOnUiThread: (() -> Unit) -> Unit) : Runnable{
override fun run() {
// stuff...
}
}
But getting compliation error for this.serverThread = Thread(ServerThread(runOnUiThread)):
I understand that it is a Java object (neither #Nullable nor #NotNull). I tried, among many other things: (() -> Unit)! and Runnable! in signature with no success. How do I fix it?
The signature of runOnUiThread in functional syntax is (Runnable) -> Unit. And you pass it as an argument using ::.
class MainActivity : AppCompatActivity() {
private lateinit var serverThread: Thread
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// stuff...
this.serverThread = Thread(ServerThread(::runOnUiThread))
this.serverThread.start()
}
}
class ServerThread(runOnUiThread: (Runnable) -> Unit) : Runnable{
override fun run() {
// stuff...
}
}
I want to get a variable from an activity and use it in another class.
This variable will be filled by an user in a editText that is called editTextSerie
override fun searchSeries(listener: OnDataListener) {
val retrofit = Retrofit.Builder().addConverterFactory(GsonConverterFactory.create())
.baseUrl("http://api.themoviedb.org/3/")
.build()
val client = retrofit.create(MovieDBApiInterface::class.java)
val objetoClasse1 = SearchActivity()
var nomeS = objetoClasse1.editTextSerie.text.toString().trim()
val responseCall = client.searchSeries("API_KEY", "pt-BR", nomeS)
responseCall.enqueue(object : Callback<AllSeriesResponse> {
override fun onResponse(call: Call<AllSeriesResponse>?, response1: Response<AllSeriesResponse>?) {
listener.onSuccess(response1!!.body()!!.results)
}
override fun onFailure(call: Call<AllSeriesResponse>?, t: Throwable?) {
listener.onFailure(t!!.message.toString())
}
})
}
This function "searchSeries" is from the class "Series".
I want to get the "editTextSerie" from another class called "Search Activity",
so i created the variable "nomeS" to receive the value of it.
class SearchActivity : AppCompatActivity() {
var botaoSearch: AppCompatImageButton? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_search)
botaoSearch = findViewById(R.id.btn_search)
botaoSearch?.setOnClickListener {
var nomeSerie = editTextSerie.text.toString().trim()
}
}
}
I want to receive this value (value of editTextSerie comes from the XML of SearchActivity ) and use it at responseCall with the "nomeS" variable
What is OnDataListener? Not really sure it is interface or abstract class, so I' ll write some pseudo code.
First change your function searchSeries's params to
searchSeries(text: String, listener: OnDataListener)
So in the class Series, you can get the data in your function searchSeries:
override fun searchSeries(text: String, listener: OnDataListener) {
// ...
// you can get the "text" string
}
Then edit your SearActivity's listener:
class SearchActivity : AppCompatActivity() {
var botaoSearch: AppCompatImageButton? = null
// create class "Series"
val series = Series()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_search)
botaoSearch = findViewById(R.id.btn_search)
botaoSearch?.setOnClickListener {
var nomeSeries = editTextSerie.text.toString().trim()
searchSeries(nomeSeries)
}
}
private fun searchSeries(text: String) {
series.searchSeries(text, object : OnDataListener {
override onSuccess(a0: ...) {
}
override onFailure(message: String) {
}
})
}
}
If OnDataListener is a abstract class:
series.searchSeries(text, object : OnDataListener() {
override onSuccess(a0: ...) {
}
override onFailure(message: String) {
}
})