onResponse variable is null in void run() - android

I'd like to get color value inside void run, how can I do this? any example?
color is null there.
public void onResponse(Call call, final Response response) throws IOException {
String color = response.body().string();
Profile.this.runOnUiThread(new Runnable() {
#Override
public void run() {
setTheme(color); //color is null here.
}
}
}
color is null inside run()
full code:
protected void onCreate(Bundle savedInstanceState) {
this.context = getApplicationContext();
OkHttpClient client = new OkHttpClient();
okhttp3.Request request = new okhttp3.Request.Builder()
.url("http://ip/color.php")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
String color = response.body().string();
Profile.this.runOnUiThread(new Runnable() {
#Override
public void run() {
setTheme(color);
}
}
}
});...

If it says variable color is accessed from within inner class,
make the variable color as Global.
Declare it outside your onCreate.
Or make it final
final String color = response.body().string();

First of all your code shouldn't compile as you cannot access non final variable inside of "closure".
So the only change you need is
final String color = response.body().string();
Profile.this.runOnUiThread(new Runnable() {
#Override
public void run() {
setTheme(color);
}
}

Related

How to set Value which is get from Common class(retrofit)

I have fragment and Common class which inside it used retrofit callback..I have Connect_and_get class.It sends request to server and gets information.I must use this information in my fragment.. But I can't return result onResponse.How can I do it..(Response is coming well from server)
Please see my code
public class Connect_and_Get {
private int size;
private OkHttpClient.Builder httpClient;
private ApiService client;
private Call<Response> call;
private MyPreference myPreference;
String a[] = {"secret"};
String b[] = {"secret"};
public int Connect_and_Get() {
Requests request;
request = new Requests("tasks.list", new params(20, 0, a, b, "", "", "", "", ""));
httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder().addHeader("Authorization", "Bearer " + "secret").build();
return chain.proceed(request);
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
client = retrofit.create(ApiService.class);
call = client.getDocument(request);
call.enqueue(new Callback<Response>() {
#Override
public void onResponse(Call<Response> call, retrofit2.Response<Response> response) {
size = response.body().getResult().getList().size();
}
#Override
public void onFailure(Call<Response> call, Throwable t) {
}
});
//retruning information
return size;
}
}
and result from common class coming 0;Because it doesn't wait my response so it is returning 0;
In fragment
Connect_and_Get a = new Connect_and_Get();
int getting = a.Connect_and_Get();
Log.d("mylog", "result:"+String.valueOf(getting));
Declare an interface like this
public interface ResponseListener {
public int onResponse(int size);
}
and use below code in your activity
public class MainActivity extends AppCompatActivity implements ResponseListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Connect_and_Get().Connect_and_Get(this);
}
#Override
public int onResponse(int size) {
// to do
return 0;
}
}
modify your connect class like this
public class Connect_and_Get {
public int Connect_and_Get(ResponseListener responseListener) {
// as it was
call.enqueue(new Callback<Response>() {
#Override
public void onResponse(Call<Response> call, retrofit2.Response<Response> response) {
size = response.body().getResult().getList().size();
responseListener.onResponse(size);
}
#Override
public void onFailure(Call<Response> call, Throwable t) {
}
});
}
}
You need to check whether your response is successful or not.
Check the code below.
call.enqueue(new Callback<Response>() {
#Override
public void onResponse(Call<Response> call, retrofit2.Response<Response> response) {
if(response.isSuccessful()){
//enter code here
} else {
//Error Message
}
}
#Override
public void onFailure(Call<Response> call, Throwable t) {
Log.e("Log", "Error -> "+t.getLocalizedMessage());
}
});
You can use an event bus like (rxbus,otto, etc..) to post events across your app when the response from the api ready to use .
Retrofit callback sample code:
call.enqueue(new Callback<Response>() {
#Override
public void onResponse(Call<Response> call, retrofit2.Response<Response> response) {
Bus.getInstance.post(Event)
}
#Override
public void onFailure(Call<Response> call, Throwable t) {
}
});
Fragment sample:
#Override
protected void onCreate(Bundle savedInstanceState) {
Bus.getInstance.register(this)
}
#Subscribe
public void onCallDone(Event response) {
//enter code here
}

web request not working on app first run

I have web request helper class in my app using OKHttp3 via standard async method call. everything just work fine, but in my Splash Activity just for first run (after new installation) web request calling not work! but if I close the app and run again everything work fine.
here is my call back interface:
public interface WebResult<T> {
void onValue(T value);}
here is calling method
public void getStatus(final WebResult result) {
urlBuilder.addQueryParameter("action", "test");
urlBuilder.addQueryParameter("reqbody", cd.toJSON());
String url = urlBuilder.build().toString();
Request request = new Request.Builder()
.header("Authorization", AuthKey)
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
setHasError(true);
setMsg(e.getMessage());
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
} else {
iAct.runOnUiThread(new Runnable() {
public void run() {
try {
String s = response.body().string();
ServerStat r = new ServerStat();
r.fromJSON(s);
result.onValue(r);
return;
} catch (IOException e) {
}
}
});
}
}
});
}
and its my splash activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
WebHelper wh = new WebHelper(context);
wh.getStatus(new WebResult() {
#Override
public void onValue(Object value) {
ServerStat r = (ServerStat) value;
if (r.getErrorCode() == 0) {
Toast.makeText(context, r.getErrorMsg(), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, r.getErrorMsg(), Toast.LENGTH_LONG).show();
}
}
});
}
I replaced OKHttp3 with google Volley and it's work in my case!

How do i save the textView text on screen rotation ? Every time i rotate the screen a new string is retrieved

#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getString();
}
private void getString(){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(URL_MOVIE)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
#Override
public void onResponse(Call call, Response response) throws IOException {
res_120 = response.body().string();
runOnUiThread(new Runnable() {
#Override
public void run() {
updateUI(res_120);
}
});
}
});
}
void updateUI(String string) {
textView.setText(string);
}
How do i save the textView text on screen rotation ? Every time i rotate the screen a new string is retrieved from the response and the my textView text changes. how stop that from happening i want to make sure that same string remains on the textview during screen rotation until and unless i update it myself by calling the getString method on say any onclicklistener to get another string for the textview.
String yourstring="";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
String myString = savedInstanceState.getString("MyString"); //get it
textView.setText(myString);
} else {
getString();
}
}
private void getString(){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(URL_MOVIE)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
#Override
public void onResponse(Call call, Response response) throws IOException {
res_120 = response.body().string();
runOnUiThread(new Runnable() {
#Override
public void run() {
updateUI(res_120);
}
});
}
});
}
void updateUI(String string) {
textView.setText(string);
yourstring=string;
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putString("MyString", yourstring); // save your instance
// etc.
super.onSaveInstanceState(savedInstanceState);
}
//onRestoreInstanceState
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
String myString = savedInstanceState.getString("MyString"); //get it
textView.setText(myString);
}
You can save your instance

getting String response from OKhttp

I want to get string JSON response to the main activity after making the connection I know it is running in different thread so please help me how I can get it and then return it from this method;
public class MakeNetworkConnection {
private String mBaseUrl;
private String mApiKey;
private String mContentType;
private String mJsonResponce;
public MakeNetworkConnection(String baseUrl, String apiKey, String contentType) {
mBaseUrl = baseUrl;
mApiKey = apiKey;
mContentType = contentType;
}
public String startNetworkConnection() throws IOException {
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder().url("http://content.guardianapis.com/sections?api-key=1123456").build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
mJsonResponce=response.body().string();
}
}
});
return mJsonResponce;
}
}
The problem here is about understanding how asynchronous tasks work. When you are calling client.newCall(request).enqueue(new Callback(), it will run in the background thread (off the main thread) and control will pass to the next line which is return mJsonResponce; And thus, it will always return null.
What you should do is to pass a callback method which will be called when the response is successful. You can create an interface to return the result:
public interface NetworkCallback {
void onSuccess(String repsonse);
void onFailure();
}
Pass an object of this interface while making the network request and call appropriate method when network request finishes.
One more thing you will have take care is that OkHttp doesn't return the response on the main thread so you will have to return the response on UI/main thread if you are going to update any UI. Something like this will work.
#Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
//return response from here to update any UI
networkCallback.onSuccess(response.body().string());
}
});
}
}
Instead of using calls asynchronously, you could use it synchronously with execute().
public String startNetworkConnection() throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://content.guardianapis.com/sections?api-key=1123456")
.build();
return client.newCall(request)
.execute()
.body()
.string();
}
after advice from Rohit Arya i did the following:
public class OkHttpUtil {
public interface OKHttpNetwork{
void onSuccess(String body);
void onFailure();
}
public void startConnection(String url, final OKHttpNetwork okHttpCallBack) throws IOException {
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()){
okHttpCallBack.onSuccess(response.body().string());
}
}
});
}
}
in the MainActvity i did the following :
OkHttpUtil okHttpUtil=new OkHttpUtil();
try {
okHttpUtil.startConnection("http://content.guardianapis.com/sections?api-key=8161f1e9-248b-4bde-be68-637dd91e92dd"
, new OkHttpUtil.OKHttpNetwork() {
#Override
public void onSuccess(String body) {
final String jsonResponse=body;
runOnUiThread(new Runnable() {
#Override
public void run() {
//show the response body
Toast.makeText(MainActivity.this,jsonResponse, Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onFailure() {
//do something
}
});
} catch (IOException e) {
e.printStackTrace();
}
Change this line
mJsonResponce=response.body().toString();
To
mJsonResponce=response.body().string();
Hope help you.

OkHTTP Update UI from enqueue callback

I am trying to use OkHTTP library. When making a call to the server and getting a successful response back. i need to update the UI.
How can this be done when doing an Async call using the enqueue()?
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
}
#Override
public void onResponse(Response response) throws IOException {
if (response.isSuccessful()) {
// NEED TO UPDATE UI HERE
}
}
});
You can refer to the following sample code, hope this helps!
public class MainActivity extends AppCompatActivity {
private static final String LOG_TAG = "OkHttp";
private TextView mTextView;
private Handler mHandler;
private String mMessage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.textView);
mHandler = new Handler(Looper.getMainLooper());
OkHttpClient client = new OkHttpClient();
// GET request
Request request = new Request.Builder()
.url("http://...")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
mMessage = e.toString();
Log.e(LOG_TAG, mMessage); // no need inside run()
mHandler.post(new Runnable() {
#Override
public void run() {
mTextView.setText(mMessage); // must be inside run()
}
});
}
#Override
public void onResponse(Response response) throws IOException {
mMessage = response.toString();
Log.i(LOG_TAG, mMessage); // no need inside run()
mHandler.post(new Runnable() {
#Override
public void run() {
mTextView.setText(mMessage); // must be inside run()
}
});
}
});
}
}
If your code doesn't update the UI, I would suggest you to specify the thread, since UI is on its own thread:
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
}
#Override
public void onResponse(Response response) throws IOException {
if (response.isSuccessful()) {
runOnUiThread(new Runnable() {
#Override
public void run() {
//TODO: update your UI
}
});
}
}
});
Try this:
Handler mainHandler = new Handler(Looper.getMainLooper());
mainHandler.post(new Runnable() {
#Override
public void run() {
// code to interact with UI
}
});
For the sake of having a clean code, I would suggest you not to put your entire code inside the runnable.
A simple example:
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://...").build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Response response) throws IOException {
final String body = response.body().string();
runOnUiThread(new Runnable() {
#Override
public void run() {
updateUI(body);
}
});
}
});
}
private void updateUI(responseBody){
//TODO: update your UI
}
}

Categories

Resources