I would like to ask assistance for my error. I used robospice-retrofit for my api and I want to get the cache. In my other sample program the I could get the cache and the value but when i used it in the fragment, I always have a null value of my cache. Btw, I created another class that would handle all my request, is there a problem with this?
Please check my codes: This is created from separate class.
public void roboretroGetTempString(final DomainResponseCallback callback,SpiceManager spiceManager){
boolean isHasCache = false;
TestStringRequest graphRequest = new TestStringRequest();
try {
if(spiceManager.isDataInCache(String.class,"graph",DurationInMillis.ONE_MINUTE).get()){
Log.e(TAG,"onRefresh:Has Cache"+spiceManager.getDataFromCache(String.class,"graph"));
}else{
/*Execute if cache has expired*/
Log.e(TAG,"onRefresh:No Cache");
spiceManager.execute(graphRequest, "graph", DurationInMillis.ONE_MINUTE, new RequestListener<String>() {
#Override
public void onRequestFailure(SpiceException spiceException) {
spiceException.printStackTrace();
callback.onApiResponse("Error", null);
}
#Override
public void onRequestSuccess(String str) {
Log.e(TAG,"onRequestSuccess:result-"+str);
}
});
}
} catch (CacheCreationException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (CacheLoadingException e) {
e.printStackTrace();
}
}
This is the code in my Fragment: DomainResponseCallback is my callback interface. I also passed the SpiceManager as a parameter that I used in the code above.
private void roboLoadTest(){
GraphController graphController = new GraphController();
graphController.roboretroGetTempString(new DomainResponseCallback() {
#Override
public void onApiResponse(String result, Object obj) {
progressBar.setVisibility(View.GONE);
Log.e(TAG,"onApiResponse-"+result);
}
#Override
public void onApiError(String error) {
Log.e(TAG,"onApiResponse-"+error);
}
},getSpiceManager());
}
This is How I set up my Fragment based on the Sample Code and extends my Fragment to this.
public class RoboFragment extends Fragment{
private String TAG = RoboFragment.class.getSimpleName();
/***
* With {#link com.octo.android.robospice.UncachedSpiceService} there is no cache management. Remember to declare it in
* AndroidManifest.xml
*/
private SpiceManager spiceManager = new SpiceManager(RoboSpiceService.class);
#Override
public void onStart() {
super.onStart();
spiceManager.start(getActivity());
}
#Override
public void onStop() {
// Please review https://github.com/octo-online/robospice/issues/96 for the reason of that
// ugly if statement.
if (spiceManager.isStarted()) {
spiceManager.shouldStop();
}
super.onStop();
}
protected SpiceManager getSpiceManager() {
return spiceManager;
}
}
This is my TestRequest`
public class TestStringRequest extends RetrofitSpiceRequest<String,RetrofitApi> {
public TestStringRequest() {
super(String.class, RetrofitApi.class);
}
#Override
public String loadDataFromNetwork() throws Exception {
return getService().getTestRetrofit();
}
}
My RetrofitApi
#GET(api_reciever+"mytestretrofit")
public String getTestRetrofit();
I don't have any idea on whats missing on my code.
Looking forward for your assistance.
A new spice manager is created/started every time a new fragment is open and that spice manager also will close. That is why you will have an empty/null cache. Check this [post].1
In my scenario, I just created a singleton extends with application and created that spicemanager in my main activity(the parent of the fragments). And It works. I don't know if this is the best solution, still searching for more better approach.
public class AppSingleton extends Application{
private static AppSingleton ourInstance = new AppSingleton();
private SpiceManager spiceManager= new SpiceManager(RoboSpiceService.class);
public static AppSingleton getInstance() {
return ourInstance;
}
public SpiceManager getSpiceManager() {
return spiceManager;
}
}
Related
I have the following AsyncTask class which I want to handle multiple api calls and return a List back to my activity. I am having a problems trying to make this work.
How can I return an object back to my activity when onPostExecute() method does not return anything?
public class NetworkCall extends AsyncTask<Call, Void, List<Student>> {
#Override
protected List<Students> doInBackground(Call... calls) {
try {
Call<Students> call = calls[0];
Response<Students> response = call.execute();
return response.body().getStudents();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(List<Students> students) {
}
}
One of the options is to create interface and use as callback.
In async task class :
public class NetworkCall extends AsyncTask<Call, Void, List<Student>> {
public interface NetworkCallback{
void onResponse(List<Students> students);
}
private NetworkCallback callback;
public void setCallback(NetworkCallback callback){
this.callback = callback;
}
#Override
protected List<Students> doInBackground(Call... calls) {
try {
Call<Students> call = calls[0];
Response<Students> response = call.execute();
return response.body().getStudents();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(List<Students> students) {
callback.onResponse(students)
}
}
and now in your activity implement the interface and provide to the async task via setter.
public class StudentsActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//.... you setup for activity
NetworkCall networkCall = new NetworkCall();
networkCall.setCallback(new NetworkCall.NetworkCallback() {
#Override
public void onResponse(List<Students> students) {
//update your UI here
}
});
}
}
Based on the Docs onPostExecute runs on the main UI thread so no need to the runOnUiThread and Runnable
you can implement like this:
Your interface:
public interface OnTaskCompleted{
void onTaskCompleted(Object o);
}
Your Activity:
public class YourActivity implements OnTaskCompleted{
// your Activity
#Override
void onTaskCompleted(Object o){
}
And your AsyncTask:
public class YourTask extends AsyncTask<Object,Object,Object>{ //change Object
to required type
private OnTaskCompleted listener;
public YourTask(OnTaskCompleted listener){
this.listener=listener;
}
// required methods
protected void onPostExecute(Object o){
// your stuff
listener.onTaskCompleted(o);
}
}
I am using rxjava 2 and trying to use rxbus for passing a value
rxbus code
public class SeasonTabSelectorBus {
private static SeasonTabSelectorBus instance;
private PublishSubject<Object> subject = PublishSubject.create();
public static SeasonTabSelectorBus instanceOf() {
if (instance == null) {
instance = new SeasonTabSelectorBus();
}
return instance;
}
public void setTab(Object object) {
try {
subject.onNext(object);
subject.onComplete();
} catch (Exception e) {
e.printStackTrace();
}
}
public Observable<Object> getSelectedTab() {
return subject;
}
}
I am setting the value as
SeasonTabSelectorBus.instanceOf().setTab(20);
This is code of my subscription
SeasonTabSelectorBus.instanceOf().getSelectedTab().subscribe(new Observer<Object>(){
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(Object o) {
if (o instanceof Integer) {
int seasonSelected =(int) o;
Log.e("season selected",seasonSelected+"");
}
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
Now I am getting the value on the first call, but when I call again with different values, I do not get the callback.
SeasonTabSelectorBus.instanceOf().setTab(40);
SeasonTabSelectorBus.instanceOf().setTab(90);
SeasonTabSelectorBus.instanceOf().setTab(120);
SeasonTabSelectorBus.instanceOf().setTab(290);
You are receiving only the first one because, after publish (subject.onNext(object)), you are calling subject.onComplete(). Just remove that line.
I am trying to send an update to my Activity from my GCMServiceListener so, I am using RxJava/RxAndroid And created a BusClass for handling sending and Observers
public class ClientBus {
//private final PublishSubject<Object> _bus = PublishSubject.create();
// If multiple threads are going to emit events to this
// then it must be made thread-safe like this instead
private final Subject<Object, Object> _bus = new SerializedSubject<>(PublishSubject.create());
public void send(Object o) {
_bus.onNext(o);
}
public Observable<Object> toObserverable() {
return _bus;
}
public boolean hasObservers() {
return _bus.hasObservers();
}
}
And in my Application Class I did this to initialize the BusClass
private ClientBus clientBus;
public ClientBus getRxBusSingleton() {
if (clientBus == null) {
clientBus = new ClientBus();
}
return clientBus;
}
In the activity I want to receive the message, I registered a CompositeSubscription and get a reference to my ClientBus class from the Application Class
clientBus = ((MyApplication) getApplicationContext()).getRxBusSingleton();
#Override
protected void onStart() {
super.onStart();
initSubscriptions();
}
#Override
protected void onStop() {
super.onStop();
_subscriptions.unsubscribe();
}
void initSubscriptions() {
_subscriptions = new CompositeSubscription();
_subscriptions.add(clientBus.toObserverable().subscribe(new Action1<Object>() {
#Override
public void call(Object event) {
Log.e("New Event", "Event Received");
if (event instanceof MyGcmListenerService.Message) {
String msg = ((MyGcmListenerService.Message) event).getMessage();
if (msg.equals("Update Available")) {
scheduleArrayList = getSchedules();
scheduleAdapter = new ScheduleAdapter(getApplicationContext(), scheduleArrayList, ScheduledUberActivity.this);
scheduledList.setAdapter(scheduleAdapter);
scheduleAdapter.notifyDataSetChanged();
} else if (msg.equals("Refresh")) {
fetchTrips();
}
}
}
}));
}
And from the MyGcmListenerService class I did this when I get a new notification
private void sendRefreshNotif() {
if (clientBus.hasObservers()) {<--It enters the if cause the Log prints. But, the activity doesn't get the message
Log.e("Obervers", "Observers aren't null");
clientBus.send(new Message("Refresh"));
}
}
What I don't understand is why isn't it working here? I use it to interact between activities and fragments. I closed my application to check if the notification comes in, It'll enter this block if (clientBus.hasObservers()) { but it didn't and starting the app and testing the Observer, it notices there's an active Observer. Any help? Thanks.
It seems like you used different instances of the ClientBus class in CompositeSubscription and MyApplication.
Try to make a singleton from ClientBus class, it works fine for me.
public class ClientBus {
public ClientBus(SingletonAccessor accessor) {}
private static ClientBus instance;
private static class SingletonAccessor{}
public static ClientBus getInstance() {
if (instance == null) instance = new ClientBus(new SingletonAccessor());
return instance;
}
private final Subject<Object, Object> mBus = new SerializedSubject<>(PublishSubject.create());
public void send(Object o) {
mBus.onNext(o);
}
public Observable<Object> toObserverable() {
return mBus;
}
public boolean hasObservers() {
return mBus.hasObservers();
}
}
I use Retrofit. Sometime I want integrate with AsyncTask for some purpose like Dialog Loading...
Here is my way:
public class RetrofitAsyncTask<T extends ResponseModel> {
public interface OnCompleteListener<T extends ResponseModel> {
public void onComplete(T t);
public void onError(Exception e);
}
public interface JsonConverter<T extends ResponseModel> {
public T getModel();
}
protected OnCompleteListener<T> onCompleteListener = null;
protected JsonConverter<T> jsonConverter;
protected ProgressDialog progressDialog;
protected int requestCode = Integer.MIN_VALUE;
public static RetrofitAsyncTask newInstance() {
return new RetrofitAsyncTask();
}
public RetrofitAsyncTask setOnCompleteListener(OnCompleteListener<T> l) {
onCompleteListener = l;
return this;
}
public RetrofitAsyncTask setJsonConverter(JsonConverter<T> converter) {
jsonConverter = converter;
return this;
}
public RetrofitAsyncTask setProgressDialog(ProgressDialog dlg) {
progressDialog = dlg;
return this;
}
public RetrofitAsyncTask setRequestCode(int reqCode) {
requestCode = reqCode;
return this;
}
public void execute() {
new AsyncTask<Void, Void, Exception>() {
private T result;
#Override
protected ProgressDialog getDialogRunOnPreStart() {
/** Retrun dialog will display. Will process on onPre & onPost. But current I will ignore it.**/
return progressDialog;
}
#Override
protected Exception doInBackground(Void... params) {
if (jsonConverter == null) {
return null;
}
try {
result = jsonConverter.getModel();
result.setRequestCode(requestCode);
} catch (Exception e) {
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception e) {
if (onCompleteListener != null) {
if (e != null || result == null) {
onCompleteListener.onError(e);
} else {
onCompleteListener.onComplete(result);
}
}
}
}.execute();
}
}
In this case class ResponseModel is Empty class.
public class ResponseModel {/** You will custom some filed default here **/}
Next you will define some Service Api.... look like:
public interface MyService {
#GET("/path")
public User getUserInfo(....);
}
(Notes class User Must be extend from ResponseModel).
Then you will custom some RetrofitAdapter...
Finally to use RetrofitAsyncTask you will do something like:
RetrofitAsyncTask.newInstance()
.setJsonConverter(
new RetrofitAsyncTask.JsonConverter<User>() {
#Override
public User getModel() {
return MyService.getUser(...);
}
}
)
.setOnCompleteListener(this)
.setRequestCode(requestCode)
.execute();
That's way I done. But current I feel it not good.
(setJsonConverter get much line :|, If you have any idea to make it better & shorter please comment ! Thanks so so much !)
In our current framework we have a base class that extends ActivityInstrumentationTestCase2 | Android Developers. Typically when we write our test case classes we inherit this base class ( lets call it FooBase) and write our methods. As you can imagine this is getting really big and I would like to refactor it so that for each area of the feature we are testing it is in its own class so that we can reuse it. Hopefully my vague classes are accurate enough The goal is just being able to split the methods into different classes and call them from my testcase
public class FooBase extends ActivityInstrumentionTestCase2 {
#Override
public void runTestOnUiThread(Runnable runnable) {
try {
super.runTestOnUiThread(runnable);
} catch (InterruptedException e) {
throw RuntimeInterruptedException.rethrow(e);
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
and our test would be eg
public class TestFooBase extends FooBase{
public void testfeature(){
//execute a method that uses super.runTestOnUiThread()
}
}
How I attempted to refactor it
public class FooHelper extends FooBase{
public FooHelper(Activity activity){
setActivity(activity)
}
public void sameMethod(){
//moved the method in FooBase to this class that uses the runTestOnUiThread
}
}
My new testcase would look something like this
public class TestFooBase extends FooBase{
FooHelper fooHelper;
public void setup(){
fooHelper = new FooHelper(getActivity);
}
public void testfeature(){
//execute a method that uses super.runTestOnUiThread()
fooHelper.callthemethod()
}
}
When I execute this I get a null pointer on the super.runTestOnUIThread.
You can pass in the entire test class and set up a constructor for it.
public class BaseTestCase {
private Instrumentation instrumentation;
private InstrumentationTestCase instrumentationTestCase;
public BaseTestCase(InstrumentationTestCase testClass, Instrumentation instrumentation){
this.instrumentationTestCase = testClass;
this.instrumentation = instrumentation;
}
public Activity getCurrentActivity() {
try {
instrumentationTestCase.runTestOnUiThread(new Runnable() {
#Override
public void run() {
//Code
}
});
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return activity;
}
To use, you want to instantiate the BaseTestCase class on the setUp method
public class ActivityTest extends ActivityInstrumentationTestCase2<TestActivity.class>{
private BaseTestCase baseTestCase;
#Override
public void setUp() throws Exception {
super.setUp();
getActivity();
baseTestCase = new BaseTestCase(this, getInstrumentation());
}
}
And to access the public methods in your BaseTestCase
public void testRun(){
baseTestCase.getCurrentActivity();
}