android Json Volley how to create interface - android

**How to create interface get only Response and set Adapter **
I have lots of json create single method pass url get response handle Error network Check
public void getJsonRequest(String url){//interface
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET,url, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
list =parseJSONRequest(response);// create interface
adapter.setAllLinks(list); // create interface
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
errorJson.setVisibility(View.VISIBLE);
String map = VolleyErrorException.getErrror(error, getContext());
errorJson.setText(map);
}
});
requestQueue.add(jsonObjectRequest);
}

you can make an interface like this :
public interface resultInterface {
void Success(JSONObject response);
void Error(VolleyError error);
}
In the mainActivity , implement resultInterface . In the getJson() method, add another parameter like this:
public void getJsonRequest(String url, final resultInterface listener){
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET,url, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
listener.Success(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
listener.Error(error);
}
});}
From your mainActivity, when call the getJsonRequest as follows:
getJsonRequest(url,this);
This will enable callbacks to your main activity.You should receive the Success and Error callbacks now.
Hope this helps!

Here is an example done in Kotlin
You can also create one like this
interface IVolley {
fun onResponse(response: String)
}
Creating requests and adding it to queue, then just call the methods and handle in MainActivity
class MyVolleyRequest
private var mRequestQueue: RequestQueue?=null
private var context: Context?=null
private var iVolley: IVolley?=null
var imageLoader: ImageLoader?=null
private set
val requestQueue: RequestQueue
get(){
if(mRequestQueue == null)
mRequestQueue = Volley.newRequestQueue(context!!.applicationContext)
return mRequestQueue!!
}
private constructor(context: Context, iVolley: IVolley)
{
this.context = context
this.iVolley = iVolley
mRequestQueue = requestQueue
this.imageLoader = ImageLoader(mRequestQueue,object: ImageLoader.ImageCache{
private val mCache = LruCache<String, Bitmap>(10)
override fun getBitmap(url: String?): Bitmap? {
return mCache.get(url!!)
}
override fun putBitmap(url: String?, bitmap: Bitmap?) {
mCache.put(url!!,bitmap!!)
}
})
}
internal constructor(context: Context)
{
this.context = context
mRequestQueue = requestQueue
this.imageLoader = ImageLoader(mRequestQueue,object: ImageLoader.ImageCache{
private val mCache = LruCache<String, Bitmap>(10)
override fun getBitmap(url: String?): Bitmap? {
return mCache.get(url!!)
}
override fun putBitmap(url: String?, bitmap: Bitmap?) {
mCache.put(url!!,bitmap!!)
}
})
}
fun <T> addToRequestQueue(req: Request<T>){
requestQueue.add(req)
}
// GET METHOD
fun getRequest(url:String)
{
val getRequest = JsonObjectRequest(Request.Method.GET,url, null, Response.Listener { response ->
iVolley!!.onResponse(response.toString())
},Response.ErrorListener { error ->
iVolley!!.onResponse(error.message!!)
})
addToRequestQueue(getRequest)
}
// POST method with params
fun postRequest(url:String)
{
val postRequest = object:StringRequest(Request.Method.POST,url,
Response.Listener { response ->
iVolley!!.onResponse(response.toString ())
},Response.ErrorListener {error -> iVolley!!.onResponse((error.message!!)) })
{
override fun getParams(): MutableMap<String, String> {
val params = HashMap<String, String>()
params["name"] = "Assad Ginem"
params["value"] = "This value is Put from Android App"
return params
}
}
addToRequestQueue(postRequest)
}
// PUT method with params
fun putRequest(url:String)
{
val postRequest = object:StringRequest(Request.Method.PUT,url,
Response.Listener { response ->
iVolley!!.onResponse(response.toString ())
},Response.ErrorListener {error -> iVolley!!.onResponse((error.message!!)) })
{
override fun getParams(): MutableMap<String, String> {
val params = HashMap<String, String>()
params["name"] = "Assad Ginem"
params["value"] = "This is value posted from Android App"
return params
}
}
addToRequestQueue(postRequest)
}
// PATCH method with params
fun patchRequest(url:String)
{
val postRequest = object:StringRequest(Request.Method.PATCH,url,
Response.Listener { response ->
iVolley!!.onResponse(response.toString ())
},Response.ErrorListener {error -> iVolley!!.onResponse((error.message!!))})
{
override fun getParams(): MutableMap<String, String> {
val params = HashMap<String, String>()
params["name"] = "Assad Ginem"
params["value"] = "This is value patch from Android App"
return params
}
}
addToRequestQueue(postRequest)
}
// DELETE method with params
fun deleteRequest(url:String)
{
val deleteRequest = StringRequest(Request.Method.DELETE, url, Response.Listener { response ->
iVolley!!.onResponse(response)
},Response.ErrorListener { error -> iVolley!!.onResponse(error.message!!)
})
addToRequestQueue(deleteRequest)
}
companion object{
private var mInstance: MyVolleyRequest? = null
#Synchronized
fun getInstance(context: Context, iVolley: IVolley): MyVolleyRequest{
if(mInstance == null)
{
mInstance = MyVolleyRequest(context,iVolley)
}
return mInstance!!
}
}
MainActivity.kt
class MainActivity : AppCompatActivity(), IVolley {
override fun onResponse(response: String) {
//Show
Toast.makeText(this#MainActivity,""+response,Toast.LENGTH_SHORT).show()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_get.setOnClickListener {
MyVolleyRequest.getInstance(this#MainActivity, this#MainActivity)
.getRequest("https://jsonplaceholder.typicode.com/todos/1")
}
btn_post.setOnClickListener {
MyVolleyRequest.getInstance(this#MainActivity, this#MainActivity)
.postRequest("https://jsonplaceholder.typicode.com/posts")
}
btn_put.setOnClickListener {
MyVolleyRequest.getInstance(this#MainActivity, this#MainActivity)
.putRequest("https://jsonplaceholder.typicode.com/posts/1")
}
btn_patch.setOnClickListener {
MyVolleyRequest.getInstance(this#MainActivity, this#MainActivity)
.patchRequest("https://jsonplaceholder.typicode.com/posts/1")
}
btn_delete.setOnClickListener {
MyVolleyRequest.getInstance(this#MainActivity, this#MainActivity)
.deleteRequest("https://jsonplaceholder.typicode.com/posts/1")
}
btn_image_loader.setOnClickListener {
image_view.setImageUrl("http://www.inspiredluv.com/wp-content/uploads/2016/10/24-cool-wallpapers.jpg"
,MyVolleyRequest(this#MainActivity).imageLoader)
}
}
}

Related

I want to call a volley request from a function that will return the arraylist to some other activity and volley response needs to converted to model

I want to get the result from volley and then parse the result to create a model arraylist and the functional that calling the volley request should return the arraylist, the function is called from various other activities and code is written by someone else so I need to figure out a way to achieve the same within this class
Here's the full class code
class Mock #Inject constructor(private val context: Context) {
val url = Constant.prefix + "get_short_videos.php"
fun loadMockData(): ArrayList<StoriesDataModel>? {
// val mockData = context.resources.openRawResource(R.raw.stories_data)
// val dataString = mockData.bufferedReader().readText()
val scope = CoroutineScope(Dispatchers.Main).launch {
val data = getData()
}
Log.e("Rresponse",dataString+"-");
val gson = Gson()
val storiesType = object : TypeToken<ArrayList<StoriesDataModel>>() {}.type
val storiesDataModelList = gson.fromJson<ArrayList<StoriesDataModel>>(dataString, storiesType)
return storiesDataModelList
}
suspend fun getData() = suspendCoroutine<String> { cont ->
val requestQueue = Volley.newRequestQueue(context)
val postRequest: StringRequest = object : StringRequest(
Method.POST, url,
Response.Listener { response: String? ->
Log.e("response",response.toString());
cont.resume(response.toString())
},
Response.ErrorListener { error: VolleyError ->
error.printStackTrace()
Toast.makeText(context, "Check your internet connection", Toast.LENGTH_SHORT)
.show()
}
) {
override fun getParams(): Map<String, String>? {
val params: MutableMap<String, String> = HashMap()
params["mobile"] = context.getSharedPreferences(Constant.prefs, Context.MODE_PRIVATE).getString("mobile","").toString();
params["length"] = "0";
return params
}
}
postRequest.retryPolicy =
DefaultRetryPolicy(
0,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
)
requestQueue.add(postRequest)
}
}
I tried various different ways given on internet but not able to figure out a way, new to kotlin so don't have much idea about Coroutine, any help is appreciated, Thanks in advance
These suspendCoroutine and CoroutineScope added by me so these might not be something that should be here
Able to figure out a way to solve the issue, here's answer if anyone needs this
class Mock #Inject constructor(private val context: Context) {
val url = Constant.prefix + "get_short_videos.php"
private var parentJob = Job()
private val coroutineContext: CoroutineContext get() = parentJob + Dispatchers.Main
private val scope = CoroutineScope(coroutineContext)
suspend fun loadMockData(): ArrayList<StoriesDataModel>? {
// val mockData = context.resources.openRawResource(R.raw.stories_data)
// val dataString = mockData.bufferedReader().readText()
var dataString = "";
// val scope = CoroutineScope(Dispatchers.Main).launch {
// dataString = getData()
// }
scope.async(Dispatchers.IO) {
val success = async { getData() }
dataString = success.await()
Log.e("Rresponse2",dataString+"-");
}.await();
Log.e("Rresponse",dataString+"-");
val gson = Gson()
val storiesType = object : TypeToken<ArrayList<StoriesDataModel>>() {}.type
val storiesDataModelList = gson.fromJson<ArrayList<StoriesDataModel>>(dataString, storiesType)
return storiesDataModelList
}
suspend fun getData() = suspendCoroutine<String> { cont ->
val requestQueue = Volley.newRequestQueue(context)
val postRequest: StringRequest = object : StringRequest(
Method.POST, url,
Response.Listener { response: String? ->
Log.e("response",response.toString());
cont.resume(response.toString())
},
Response.ErrorListener { error: VolleyError ->
error.printStackTrace()
Toast.makeText(context, "Check your internet connection", Toast.LENGTH_SHORT)
.show()
}
) {
override fun getParams(): Map<String, String>? {
val params: MutableMap<String, String> = HashMap()
params["mobile"] = context.getSharedPreferences(Constant.prefs, Context.MODE_PRIVATE).getString("mobile","").toString();
params["length"] = "0";
return params
}
}
postRequest.retryPolicy =
DefaultRetryPolicy(
0,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
)
requestQueue.add(postRequest)
}
}
Also requires to make function suspended from the main function called

How should I implement my AsyncTask class?

I am making a weather app, where I use AsyncTask for getting response from API and after that setting up the UI. Here how looks like my code now after simplyfing:
class MainActivity : AppCompatActivity() {
/*
SOME INSIGNIFICANT CODE HERE
*/
private fun setUI(currentWeather: Root){
tv_city.text = "${currentWeather.name}, ${currentWeather.sys.country}"
/*
...
*/
}
inner class WeatherByNameTask: AsyncTask<String, Unit, Unit>(){
override fun doInBackground(vararg p0: String?) {
val city: String? = p0[0]
val call = weatherApi.getCurrentWeatherByCityName(city!!, API_KEY, "metric")
call.enqueue(object: Callback<Root>{
override fun onResponse(call: Call<Root>, response: Response<Root>) {
if (!response.isSuccessful){
Toast.makeText(this#MainActivity, "Code: ${response.code()}", Toast.LENGTH_LONG).show()
} else {
val currentWeather = response.body()
setUI(currentWeather!!)
}
}
override fun onFailure(call: Call<Root>, t: Throwable) {
Toast.makeText(this#MainActivity, "Code: ${t.message}", Toast.LENGTH_LONG).show()
}
})
}
}
inner class WeatherByCoordTask: AsyncTask<Location, Unit, Unit>(){
override fun doInBackground(vararg p0: Location?) {
val lat: String = p0[0]?.latitude.toString()
val lon: String = p0[0]?.longitude.toString()
val call = weatherApi.getCurrentWeatherByCoordinates(lat, lon, API_KEY, "metric")
call.enqueue(object: Callback<Root>{
#SuppressLint("SetTextI18n")
override fun onResponse(call: Call<Root>, response: Response<Root>) {
if (!response.isSuccessful){
Toast.makeText(this#MainActivity, "Code: ${response.code()}", Toast.LENGTH_LONG).show()
} else {
val currentWeather = response.body()
setUI(currentWeather!!)
}
}
override fun onFailure(call: Call<Root>, t: Throwable) {
Toast.makeText(this#MainActivity, "Code: ${t.message}", Toast.LENGTH_LONG).show()
}
})
}
}
}
It works, but I'm getting a warning:
This AsyncTask class should be static or leaks might occur
I want to make it in correct way. I tried to implement it outside the MainActivity class, passing the Context as a parameter, but what's about setUI function? I guess making it public is bad idea.
This AsyncTask class should be static or leaks might occur
In the MainActivity, there are 2 AsyncTask class with inner modifier, this means the inner class will keep a strong reference to the outer class. The warning tells you while the AsyncTask is doing its job in the background, if the user leaves the current activity (press Back key or calling finish() method), then the activity instance will be leaked because the AsyncTask still keeps a strong reference to it.
Solution
Using WeakReference to let the AsyncTask keeps a weak reference to the MainActivity.
class WeatherByNameTask (activity: MainActivity): AsyncTask<String, Unit, Unit>(){
private val activityRef = WeakReference<MainActivity>(activity)
override fun doInBackground(vararg p0: String?) {
val city: String? = p0[0]
val call = weatherApi.getCurrentWeatherByCityName(city!!, API_KEY, "metric")
call.enqueue(object: Callback<Root>{
override fun onResponse(call: Call<Root>, response: Response<Root>) {
if (!response.isSuccessful){
activityRef.get()?.let {
Toast.makeText(it, "Code: ${response.code()}", Toast.LENGTH_LONG).show()
}
} else {
val currentWeather = response.body()
activityRef.get()?.setUI(currentWeather!!)
}
}
override fun onFailure(call: Call<Root>, t: Throwable) {
activityRef.get().let {
Toast.makeText(it, "Code: ${t.message}", Toast.LENGTH_LONG).show()
}
}
})
}
}
class WeatherByCoordTask (activity: MainActivity): AsyncTask<Location, Unit, Unit>(){
private val activityRef = WeakReference<MainActivity>(activity)
override fun doInBackground(vararg p0: Location?) {
val lat: String = p0[0]?.latitude.toString()
val lon: String = p0[0]?.longitude.toString()
val call = weatherApi.getCurrentWeatherByCoordinates(lat, lon, API_KEY, "metric")
call.enqueue(object: Callback<Root>{
#SuppressLint("SetTextI18n")
override fun onResponse(call: Call<Root>, response: Response<Root>) {
if (!response.isSuccessful){
activityRef.get()?.let {
Toast.makeText(it, "Code: ${response.code()}", Toast.LENGTH_LONG).show()
}
} else {
val currentWeather = response.body()
activityRef.get()?.setUI(currentWeather!!)
}
}
override fun onFailure(call: Call<Root>, t: Throwable) {
activityRef.get().let {
Toast.makeText(it, "Code: ${t.message}", Toast.LENGTH_LONG).show()
}
}
})
}
}
Use from the activity
val weatherByNameTask = WeatherByNameTask(this)
val weatherByCoordTask = WeatherByCoordTask(this)
Following is the way how to make AsyncTask :
private class AsyncTaskGetPlaces extends AsyncTask<Void, Void, AsyncTaskResult<Object>>
{
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected AsyncTaskResult<Object> doInBackground(Void... params)
{
try
{
LibHttp libHttp = new LibHttp();
String res = libHttp.listBusiness("21","test#ns.com");
return new AsyncTaskResult<Object>(res);
}
catch (Exception e)
{
e.printStackTrace();
return new AsyncTaskResult<Object>(e);
}
}
#Override
protected void onPostExecute(AsyncTaskResult<Object> result)
{
if(result.getError()!= null)
{
showOKAlertMsg("App",getResources().getString(R.string.txt_data_not_found), false);
}
else
{
String res = result.getResult().toString();
try {
JSONObject resObj = new JSONObject(res);
if(resObj.getString("status_code").equals("1")){
//parse
// Do your task here
}
} catch (JSONException e) {
e.printStackTrace();
showOKAlertMsg("",getResources().getString(R.string.txt_internal_server_error), false);
}
}
}
}
Where AsyncTaskResult is
public class AsyncTaskResult<T>
{
private T result;
private Exception error;
public T getResult()
{
return result;
}
public Exception getError()
{
return error;
}
public AsyncTaskResult(T result)
{
this.result = result;
}
public AsyncTaskResult(Exception error)
{
this.error = error;
}
}

Can not override getParam in Kotlin (Volley)

I can not override getParam like shown below. I hope someone can explain how to override getParam in Kotlin.
build.gradle
implementation 'com.android.volley:volley:1.1.1'
fun testpost(button: Button)
{
val url = "http://192.168.178.23/insertcode.php"
val queue = Volley.newRequestQueue(this)
val stringRequest = StringRequest(Request.Method.POST, url,
{ response ->
button.text = "Response is: ${response}"
},
{ button.text = "That didn't work!" })
{
override fun getParam(){
}
}
queue.add(stringRequest)
}
Typing object before StringRequest and now the method getParams is available.
The code looks like this:
fun testpost(button: Button)
{
val url = "http://192.168.178.23/insertcode.php"
val queue = Volley.newRequestQueue(this)
val stringRequest = object :StringRequest(Request.Method.POST, url,
{ response ->
button.text = "Response is: ${response}"
},
{ button.text = "That didn't work!" })
{
//Press Ctr + O to find getParams
override fun getParams(): MutableMap<String, String> {
val hashMap = HashMap<String, String>()
hashMap.put("name", "peter")
return hashMap
}
}
queue.add(stringRequest)
}
You can't, it's not exposed in StringRequest or any other built in request for that matter. If that's indeed what you need to do, you have to unfortunately create your own custom request.
Below is an example for a Custom StringRequest which allows us to specify params in its constructor (Kotlin):
import androidx.annotation.GuardedBy
import com.android.volley.NetworkResponse
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.HttpHeaderParser
import java.io.UnsupportedEncodingException
import java.nio.charset.Charset
class CustomStringRequest(
method: Int,
url: String,
listener: Response.Listener<String>,
errorListener: Response.ErrorListener?,
private val params: MutableMap<String, String>
) : Request<String>(method, url, errorListener) {
private val lock = Any()
#GuardedBy("lock")
private var listener: Response.Listener<String>? = listener
override fun getParams(): MutableMap<String, String> {
return params
}
override fun cancel() {
super.cancel()
synchronized(lock) { listener = null }
}
override fun deliverResponse(response: String) {
var listener: Response.Listener<String>?
synchronized(lock) { listener = this.listener }
if (listener != null) {
listener!!.onResponse(response)
}
}
override fun parseNetworkResponse(response: NetworkResponse): Response<String> {
val parsed: String = try {
String(response.data, Charset.forName(HttpHeaderParser.parseCharset(response?.headers)))
} catch (e: UnsupportedEncodingException) {
// Since minSdkVersion = 8, we can't call
// new String(response.data, Charset.defaultCharset())
// So suppress the warning instead.
String(response.data)
}
return Response.success(
parsed,
HttpHeaderParser.parseCacheHeaders(response)
)
}
}
You would then use it like:
// Instantiate the RequestQueue.
val queue = Volley.newRequestQueue(activity)
val url = "YOUR_URL"
// Request a string response from the provided URL.
val stringRequest = CustomStringRequest(
Request.Method.POST, url,
Response.Listener { response ->
// TODO do something with response
},
Response.ErrorListener {
// TODO handle errors
},
hashMapOf("name" to "value") // TODO add your params here
)
// Add the request to the RequestQueue.
queue.add(stringRequest)

How to callback a value from Volley On Response function in Kotlin

I am integrating a Login System for that I want the Response.Listener and Response.ErrorListener function to return a Boolean.
I searched on the google and found that it can be done using a callback interface ( This Question ). But I don't know how to do that in Kotlin
[ALSO UPDATED] This is my Kotlin file containing my function which are used by many activities:
package com.pratham.example
// My required imports
import ...
fun function1(){
...
}
fun function2(){
...
}
// This Auth function will return True if login success
fun auth(activity:Activity):Boolean{
val queue = Volley.newRequestQueue(activity)
val req = JsonObjectRequest(Request.Method.POST, url, jsonObj,
Response.Listener { response ->
val JSONObj = response.getString("Status")
if(JSONObj=="200"){
// return true
}
else{
// return false
}
}, Response.ErrorListener {
// return false
}
)
queue.add(req)
}
fun function4(){
...
}
This function will return true or false according to the Volley Response.
How can i return value from a Response.Listener and Response.ErrorListener in Kotlin
Edit:: I tried to use Interface like this
package com.pratham.sitapuriya
import ...
fun function1(){
...
}
fun function2(){
...
}
interface MyInterface {
fun onCallback(response: Boolean,context:Context)
}
class Login : MyInterface {
private val myInterface = this
override fun onCallback(response: Boolean,context:Context) {
Toast.makeText(context,"Working",Toast.LENGTH_SHORT).show()
}
fun auth(activity: Activity): Boolean {
val sp1 = activity.getSharedPreferences("Login", AppCompatActivity.MODE_PRIVATE)
if (sp1.contains("token") && sp1.contains("deviceId")) {
val token = sp1.getString("token", null)
val deviceId = sp1.getString("deviceId", null)
if (!token.isNullOrEmpty() && !deviceId.isNullOrEmpty()) {
// val url = "http://10.0.2.2:80/Projects/Sitapuriya/login.php"
val url = activity.getString(R.string.server) + "/tokenAuth.php"
val params = HashMap<String, String>()
params["token"] = token
params["deviceId"] = deviceId
val jsonObj = JSONObject(params)
val queue = Volley.newRequestQueue(activity)
val req = JsonObjectRequest(Request.Method.POST, url, jsonObj,
Response.Listener { response ->
val JSONObj = response.getString("Status")
if (JSONObj == "200") {
// return true
myInterface.onCallback(true,activity)
} else {
// return false
myInterface.onCallback(false,activity)
}
}, Response.ErrorListener {
// return false
myInterface.onCallback(false,activity)
}
)
queue.add(req)
} else {
return false
}
} else {
return false
}
return false
}
}
fun function4(){
...
}
But now i have no idea that how the callback will return value in auth() function and also how I'll be calling this auth() fucntion in my other activities .
Please help I have never used a callback before..
You can't, the code you have executes asynchronously so you can't have the return statement there.
But it doesn't mean you can not get the value. The easiest option is create a LiveData<Boolean> and observe it in your activity. When the value changes you will get notified.
The next thing you can do is you can create an interface.
interface MyCallback{
fun onValueChanged()
}
Then implement this interface in your activity and override the method. Then you can use it to get a callback when your asynchronous call finishes. See the below code.
interface MyInterface{
fun onCallback(response:Boolean)
}
class LoginActivity : AppCompatActivity(), AuthListener, MyInterface {
val myInterface = this
override fun onCallback(response: Boolean) {
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val queue = Volley.newRequestQueue(activity)
val req = JsonObjectRequest(Request.Method.POST, url, jsonObj,
Response.Listener { response ->
val JSONObj = response.getString("Status")
if(JSONObj=="200"){
//return true
myInterface.onCallback(true)
}
else{
myInterface.onCallback(false)
}
}, Response.ErrorListener {
// return false
}
)
queue.add(req)
}
}
Hope this helps. Thank You :)

Coroutine calling API Android

I have to call an API asynchronously. To do it i'm using a coroutine, but i have to wait until the API is called to load the data. The problem is the next:
The await is not working as I want, it's not waiting until the API gives all the data.
Is the await what I need? Here is the code:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_see)
launch { loaddata() }
/* some other code here*/
}
suspend fun loadData(){
val readData = async { read() }
readData.join()
readData.await()
val showScreen = async { refreshList() }
showScreen.join()
showScreen.await()
}
fun read(){
val stringRequest = object : StringRequest(Request.Method.POST, URL, Response.Listener<String>{ s ->
try {
val array = JSONArray(s)
for (i in 0..array.length() - 1) {
val objectAccount = array.getJSONObject(i)
val account = Account(
objectAccount.getString(value),
objectAccount.getString(value),
objectAccount.getString(value))
listAccount.add(account)
}
}catch (e: JSONException){
e.printStackTrace()
}
}, Response.ErrorListener { error: VolleyError? -> Log.e("error", "error") }){
override fun getParams(): Map<String, String> {
val params = HashMap<String, String>()
params.put("password", value)
params.put("idaccount", value)
return params
}
}
val requesQueue = Volley.newRequestQueue(this)
requesQueue.add<String>(stringRequest)
}
Usually you shouldn't call a async function
requesQueue.add<String>(stringRequest)
in the async coroutine builder
async {}
Sulution #1
you can change your read() method to a synchronous request.
Can I do a synchronous request with volley?
and run it with CommonPool
async(CommonPool) {
read()
}
Solution #2
wrap your async http call into a suspend function
I am NOT familiar with Volley, so maybe the code needs tweak
suspend fun read() {
return suspendCancellableCoroutine { continuation ->
val stringRequest = object : StringRequest(Request.Method.POST, URL, Response.Listener<String> { s ->
try {
val array = JSONArray(s)
for (i in 0..array.length() - 1) {
val objectAccount = array.getJSONObject(i)
val account = Account(
objectAccount.getString(value),
objectAccount.getString(value),
objectAccount.getString(value))
listAccount.add(account)
}
} catch (e: JSONException) {
e.printStackTrace()
// notice this
continuation.resumeWithException(e)
}
// notice this
continuation.resume()
}, Response.ErrorListener { error: VolleyError? ->
Log.e("error", "error")
// notice this
if (!continuation.isCancelled)
continuation.resumeWithException()
}) {
override fun getParams(): Map<String, String> {
val params = HashMap<String, String>()
params.put("password", value)
params.put("idaccount", value)
return params
}
}
val requesQueue = Volley.newRequestQueue(this)
requesQueue.add<String>(stringRequest)
continuation.invokeOnCompletion {
if (continuation.isCancelled)
try {
cancel()
} catch (ex: Throwable) {
//Ignore cancel exception
}
}
}
}
and call it like this
suspend fun loadData(){
read()
val showScreen = async { refreshList() }
showScreen.join()
showScreen.await()
}

Categories

Resources