I'm using retrofit2 to get data from web service, but when I called notify() from thread , main thread cannot get it . And hang app , I don't know why . I hope someone can help me .
OnCreate()
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
synchronized (listRespones) {
while (listRespones.size() < 2) {
try {
listRespones.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Thread 1:
apiManager.getChannelListRespone(areaCode).enqueue(new Callback<CommonListRespone>() {
#Override
public void onResponse(Call<CommonListRespone> call, final Response<CommonListRespone> response) {
Thread channel1 = new Thread(new Runnable() {
#Override
public void run() {
synchronized (listRespones) {
CommonListRespone commonChannel = response.body();
listRespones.add(commonChannel);
listRespones.notify();
}
}});
channel1.start();
}
#Override
public void onFailure(Call<CommonListRespone> call, Throwable t) {
}});
Thread 2:
apiManager.getChannelListRespone(areaCode).enqueue(new Callback<CommonListRespone>() {
#Override
public void onResponse(Call<CommonListRespone> call, final Response<CommonListRespone> response) {
Thread channel2 = new Thread(new Runnable() {
#Override
public void run() {
synchronized (listRespones) {
CommonListRespone commonChannel = response.body();
listRespones.add(commonChannel);
listRespones.notify();
}
}
});
channel2.start();
}
#Override
public void onFailure(Call<CommonListRespone> call, Throwable t) {
}
});
Related
I am trying to use thread wait and notify function, but noticed that notify function not calling my method again. Sharing my code. Please let me know what I'm doing wrong.
public class MainActivity extends AppCompatActivity {
Thread t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
t = new Thread(new Runnable() {
#Override
public void run() {
List<Parent> threadList = new ArrayList<>();
threadList.add(new Task1(MainActivity.this));
threadList.add(new Task2(MainActivity.this));
for (Parent task : threadList) {
try {
task.execute();
t.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
}
public void getResult(int i) {
Log.i("###","Notified"+i);
t.notify();
}
}
class Task1 implements Parent{
public int total;
MainActivity mainActivity;
Task1 (MainActivity c) {
mainActivity = c;
}
#Override
public void execute() {
for(int i=0; i<200 ; i++){
total += i;
Log.i("###1", ""+i);
}
mainActivity.getResult(1);
}
}
Task 2 is not getting executed after Task1
Im using OkHttpClient to connect to an API.
Request request = new Request.Builder()
.url(BPI_ENDPOINT)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Toast.makeText(Test.this, "Error during BPI loading : "
+ e.getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(Call call, Response response)
throws IOException {
final String body = response.body().string();
runOnUiThread(new Runnable() {
#Override
public void run() {
parseBpiResponse(body);
}
});
}
});
The parseBpiResponse just displays the data in TextView but the data request from the site takes place only once and in order to get the data again I need to either reopoen the activity or implement a button or swipe-screen etc,
How to call an API request constantly so that the data keeps updating instead of doing it through users input??
you can use Timer class to do a network call periodically
final long period = 0;
new Timer().schedule(new TimerTask() {
#Override
public void run() {
// do your task here
}
}, 0, period);
use this code but you should be careful about your activity and views in this code it my lead to nasty exception and memory leaks better thing to do is using live data with Recursion function !
new Thread(new Runnable() {
#Override
public void run() {
//Checks the life cycle of the activity and if activity was destroyed break the while loop and exits
while (true && getLifecycle().getCurrentState() != Lifecycle.State.DESTROYED) {
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Toast.makeText(Test.this, "Error during BPI loading : "
+ e.getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(Call call, Response response)
throws IOException {
final String body = response.body().string();
runOnUiThread(new Runnable() {
#Override
public void run() {
if (getLifecycle().getCurrentState() != Lifecycle.State.DESTROYED)
parseBpiResponse(body);
}
});
}
});
try {
//Waits for 1 sec
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
Just make a recursive call .for example :
public void callAPI()
{
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Toast.makeText(Test.this, "Error during BPI loading : "
+ e.getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(Call call, Response response)
throws IOException {
final String body = response.body().string();
runOnUiThread(new Runnable() {
#Override
public void run() {
parseBpiResponse(body);
}
});
**//just use handler/timer or thread to post event after some interval**
new android.os.Handler().postDelayed(new Runnable() {
#Override
public void run() {
callAPI();
}
},2000);
}
});
}
Also i suggest using Rxjava+Retrofit with OkHttp and use interval function to make it easier .
i want to know that should i run my functions in a thread or write functions code in a thread!
my mean is something like this:
here i used my function in a thread
...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_disable_stable_mode);
new Thread(new Runnable() {
#Override
public void run() {
function1();
function2();
function3();
}
}).start();
}
void function1(){
//some code
}
void function2(){
//some code
}
void function3(){
//some code
}
...
and here i used one thread for every function:
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_disable_stable_mode);
function1();
function2();
function3();
}
void function1(){
new Thread(new Runnable() {
#Override
public void run() {
//some code
}
}).start();
}
void function2(){
new Thread(new Runnable() {
#Override
public void run() {
//some code
}
}).start();
void function3(){
new Thread(new Runnable() {
#Override
public void run() {
//some code
}
}).start();
...
are are they same in performance?
the first sample code will be execute
function1() and then function2() and then function3()
but
in second sample code will be execute
function1() and function2() and function3() simultaneously
they are not the same method1 different from method2
I want to call adapter.notifyDataSetChanged() from another thread. I read that I should use an AsyncTask and do the adapter.notifyDataSetChanged() in post execute.
I must execute the AsyncTask every 5 seconds only on the current activity (might be parent or child activity) because only one activity can do the asynctask at the same time.
Should I create a TimerTask which executes the AsyncTask every 5 seconds, stop it when I start another activity and start it back in onResume ?
Here is my code for the thread which updates the ListView of the current Activity.
private void runEventHandler() {
new Thread() {
public void run() {
while (true) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
users.add(new User(10, "a", false));
adapter.notifyDataSetChanged();
}
});
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
Now I must be able to update the child activities' ListViews when a new User is added.
one possible way is that you create a flag in both activity to control your threads to be run ( the following codes are not runable just example to understand what you can do):
Activity A
{
public static boolean stopThread = false;
#Override
public void onResume()
{
super.onResume();
// put your code here...
stopThread =false;
runEventHandler();
}
private void runEventHandler() {
new Thread() {
public void run() {
while (A.stopThread != false) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
users.add(new User(10, "a", false));
adapter.notifyDataSetChanged();
}
});
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
#Override
protected void onStop(){
super.onStop();
stopThread =true;
}
}
Activity B
{
public static boolean stopThread = false;
#Override
public void onResume()
{
super.onResume();
// put your code here...
stopThread =false;
runEventHandler();
}
private void runEventHandler() {
new Thread() {
public void run() {
while (B.stopThread != false) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
users.add(new User(10, "a", false));
adapter.notifyDataSetChanged();
}
});
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
#Override
protected void onStop(){
super.onStop();
stopThread =true;
}
}
also you can use onPause() instead of onStop(). depends on your program concept.
You should a timertask like in link below : https://examples.javacodegeeks.com/android/core/activity/android-timertask-example/
the code to post any change on UIThread if you are in a different thread like doInBackground of AsyncTask:
runOnUiThread(new Runnable() {
#Override
public void run() {
// Here you can set your Ui Components
}
});
I am trying to show a progress indicator when doing network requests with volley. I am getting the error "Only the original thread that create a view hierarchy can touch its views". I cannot figure out how to get my hideProgressDialog() onto the same thread as showProgressDialog(). Here's my code...
showProgressDialog("Logging you in");
String url = ApplicationController.getInstance().getBaseURL() + "Customer/LoginCustomer";
JsonRequest<String> jr = new JsonRequest<String>(Method.POST, url, jo.toString(), this.createSuccessListener(),
this.createErrorListener()) {
#Override
protected Response<String> parseNetworkResponse(NetworkResponse nr) {
hideProgressDialog();
try {
String str = new String(nr.data, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
};
ApplicationController.getInstance().addToRequestQueue(jr);
}
/** Create Volley Listeners **/
private Response.ErrorListener createErrorListener() {
return new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
hideProgressDialog();
}
};
}
private Response.Listener<String> createSuccessListener() {
return new Response.Listener<String>() {
#Override
public void onResponse(String response) {
hideProgressDialog();}
};
}
Solution
Thanks to tautvydas. I ended up putting these methods in my base class.
protected void showProgressDialog(String message) {
if(mHandler == null){
mHandler = new Handler();
}
if (mDialog == null || !mDialog.isShowing()) {
mDialog = new ProgressDialog(getActivity());
mDialog.setMessage(message);
mDialog.setCancelable(false);
mDialog.setIndeterminate(true);
mDialog.show();
}
}
protected void hideProgressDialog() {
if (mDialog != null) {
mHandler.post(new Runnable() {
#Override
// this will run on the main thread.
public void run() {
mDialog.hide();
}
});
}
}
Create a Handler and pass a Runnable to it to run on the main thread.
1) Declare Handler in the constructor on onCreate() method by Handler handler = new Handler(). 2) Then in your parseNetworkResponse() method call
handler.post(new Runnable() {
#Override
// this will run on the main thread.
public void run() {
hideProgressDialog();
}
});