I'm implementing LoaderManager.LoaderCallbacks on my MainActivity and I'm overriding onCreateLoader. In the onCreateLoader I simply return a AsyncTaskLoader object, where I override the onStartLoading method, in which I check if the query is null. For this code works, I need to call forceLoad(). Here is a snippet of the code:
#Override
public Loader<String> onCreateLoader(int id, final Bundle args) {
return new AsyncTaskLoader<String>(this) {
#Override
protected void onStartLoading() {
// No need to peform a query if no arguments were passed
if (args == null) {
return;
}
// This needs to be called!!
forceLoad();
}
#Override
public String loadInBackground() {
/* some code */
}
};
}
The problem is that I don't know why I need to call forceLoad(), because its implementation is a "empty" method. In the source code of the Loader Class, the implementation of forceLoad is:
public void forceLoad() {
onForceLoad();
}
and the implementation of onForceLoad() is:
protected void onForceLoad() {
}
I tried to find some methods that override forceLoad() or onForceLoad in the other parts of the code (I use (getSupportLoaderManager().initLoader(arg1, arg2, arg3)), but until this moment have not succeeded. Why do I have to call forceLoad() and why does it work?
The reason Loader class is having empty implementation of onForceLoad() is that Loader is a base class. Their child classes are supposed to be implementing onForceLoad().
If we will see your code, you are using AsyncTaskLoader which basically a child of Loader so AsyncTaskLoader will have the onForceLoad() implementation which is actually this:
#Override
protected void onForceLoad() {
super.onForceLoad();
cancelLoad();
mTask = new LoadTask();
if (DEBUG) Slog.v(TAG, "Preparing load: mTask=" + mTask);
executePendingTask();
}
Your onCreateLoader()basically should be like this:
public Loader<String> onCreateLoader(int id, final Bundle args) {
AsyncTaskLoader<String> loader = new AsyncTaskLoader<String>(this) {
#Override
protected void onStartLoading() {
// No need to peform a query if no arguments were passed
if (args == null) {
return;
}
}
#Override
public String loadInBackground() {
/* some code */
}
};
loader.forceLoad(); // This basically gonna run the loader.
return loader;
}
We can also override the onStartLoading() method to call forceLoad() which is a required step to actually trigger the loadInBackground() method to execute.
public class Loader extends AsyncTaskLoader<List<data>> {
// Tag for Log messages
private static final String LOG_TAG = Loader.class.getName();
// Query URL
private String mUrl;
/**
* Constructs a new {#link data}
*
* #param context of the activity
* #param url to load the data from
*/
public Loader (Context context, String url) {
super(context);
mUrl = url;
}
#Override
protected void onStartLoading() {
forceLoad();
}
/**
* This is on the background thread
*/
#Override
public List<data> loadInBackground() {
if(mUrl == null) {
return null;
}
// Perform the network request, parse the response and extract a list of data.
List<data> data= QueryUtils.fetchData(mUrl);
return data;
}
}
Related
I'm trying to create couple of Java class to perform certain work. Let's say I want to get the task done by calling my classes like this:
FirebaseAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithCredential:success");
FirebaseUser user = task.getResult().getUser();
// ...
} else {
// Sign in failed, display a message and update the UI
Log.w(TAG, "signInWithCredential:failure", task.getException());
if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
// The verification code entered was invalid
}
}
}
});
I could understand up to signInWithCredential(). I can't figure out how to implement addOnCompleteListener() and have a interface as argument.
I've currently create my top class like FirebaseAuth with methods like getInstance () and signInWithCredential(). Also, I tried creating an interface but I am getting error that result of the interface is never used. How can I implement the style of addOnCompleteListener(parameter 1, interface 2).
Here, addOnCompleteListener is getting parameters of activity and interface and in my case, I will be using the activity parameter for some work.
P.S: I found out this is called interface callback. If it's right, any guidance to it's structure will be great
You can do it like this:
Create an interface:
public interface onCompleteListener {
void onComplete(MyTask object);
}
Define your MyTask class:
public abstract class MyTask {
public abstract boolean someFunc1();
public abstract String someFunc2();
public abstract String someFunc3();
}
In your main class:
public class MainClass{
public static MainClass instance;
private static Activity mActivity;
public onCompleteListener onCompleteListener;
private MainClass(Activity activity) {
mActivity = activity;
}
public static synchronized MainClass getInstance(Activity activity) {
if (instance == null) {
instance = new MainClass(activity);
}
return instance;
}
public void addOnCompleteListener(#NonNull onCompleteListener var2) {
onCompleteListener = var2;
//Call your task function
doTask();
}
public void doTask(){
MyTask o = new MyTask() {
#Override
public boolean someFunc1() {
return true;
}
#Override
public String someFunc2() {
return "";
}
#Override
public String someFunc3 {
return "";
}
};
//Once done, pass your Task object to the interface.
onCompleteListener.onComplete(o);
}
}
Usage:
MainClass.getInstance(MainActivity.this).addOnCompleteListener(new onCompleteListener() {
#Override
public void onComplete(MyTask object) {
doYourWork(object);
}
});
I have these two methods declared:
private Result mResult;
private void setResult(Result result){
this.mResult = result;
}
private Result getResult(){
new Executor(new OnResultListener() {
#Override
public void onResult(Result result) {
setResult(result);
}
}).execute();
return mResult;
}
Im using an interface while an AsyncTask is executing. What my problem is, is that I want to return the Result object of the onResult method as an object to the getResult() method.
As shown above, I tried to set it through a setter, but it seems that this is not working.
How can I succeed that?
Thanks in advance!
You have two options here. The bad one is to wait until the new thread will finish. let's don't do that). the better way is to use a callback for:
public static interface OnResultCallback {
void onResult(Result result);
}
private void getResult(final OnResultCallback callback){
new Executor(new OnResultListener() {
#Override
public void onResult(Result result) {
setResult(result);
callback.onResult(result);
}
}).execute();
}
You could provide an instance of OnResultListener as part of the constructor of your AsyncTask, which the caller has to implement. E.g.
private Result mResult;
private OnResultListener mListener;
private void setResult(Result result, OnResultListener listener){
this.mResult = result;
mListener = listener;
}
private Result getResult(){
new Executor(new OnResultListener() {
#Override
public void onResult(Result result) {
if (mListener != null) {
mListener.onResult(result);
}
setResult(result);
}
}).execute();
return mResult;
}
or you could directly provide mListener to new Executor
public class CustomOnResultListener extends OnResultListener{
Callback callback ;
public CustomOnResultListener(Callback callback){}
this.callback =callback; // use this callback to send result
}
public interface Callback{public void onCallback(Result result);};
I have a "Data manager" class, which contains a list of some sort of object type
Then, when I started getting my code advanced, I had the need for a different kind of manager, which has some similarities - loadData(..), saveData(..), add(..), remove(..)
but also some differences, which is unique to each kind of manager, depending on the type of which it is "managing".
So I decided to do the following structure:
Generic class with singelton implementation for each child (At first, my manager was static as it has no sense of being multiple instances):
public abstract class GenericDataManager<T> {
protected List<T> list;
protected void saveData(Context context, String filePath) {..}
protected void loadData(Context context, String filePath) {..}
..
}
and my two managers are the following:
public class ManagerA extends GenericDataManager<A> {
private static ManagerA instance = null;
protected ManagerA() { }
public static ManagerA getInstance() {
if (instance == null)
instance = new ManagerA();
return instance;
}
private void saveData(Context context) {
saveData(context, "fileA");
}
private void loadData(Context context) {
loadData(context, "fileA");
}
}
public class ManagerB extends GenericDataManager<B> {
private static ManagerB instance = null;
protected ManagerB() { }
public static ManagerB getInstance() {
if (instance == null)
instance = new ManagerB();
return instance;
}
private void saveData(Context context) {
saveData(context, "fileB");
}
private void loadData(Context context) {
loadData(context, "fileB");
}
}
I showed here only the similar pieces of code for the two managers, and you can already see the problem - Although I managed to make my similar piece of code implemented only one and reused for every specific implementation using generics and inheritance mechanism, I still need the only specific information, which is the data file to use.
Is there a way of the generic parent to request that information from its child, so that I wont need the redundant implementation in the child class?
Leaving it this way makes me feel Im missing something.
How about:
public abstract class GenericDataManager<T> {
protected abstract String getFilePath();
protected List<T> list;
protected void saveData(Context context) {
String filePath = getFilePath();
..
}
protected void loadData(Context context) {
String filePath = getFilePath();
..
}
..
}
and then:
public class ManagerA extends GenericDataManager<A> {
private static ManagerA instance = null;
protected ManagerA() { }
public static ManagerA getInstance() {
if (instance == null)
instance = new ManagerA();
return instance;
}
protected String getFilePath() { return "fileA" );
}
public class ManagerB extends GenericDataManager<A> {
private static ManagerB instance = null;
protected ManagerB() { }
public static ManagerB getInstance() {
if (instance == null)
instance = new ManagerB();
return instance;
}
protected String getFilePath() { return "fileB" );
}
You could have the parent call back to the children, but it's generally poor practice. Inheritance always requires tightly coupling the children to the parent, but you generally want to avoid coupling the parent to the children.
Instead, perhaps in GenericDataManager:
protected void saveData(Context context, string fileName) {
// do the generic work with the specific given file
}
protected void loadData(Context context) {
// do the generic work with the specific given file
}
...and then in the subclasses:
private void loadData(Context context) {
super.loadData(context, "loadA"); // or of course, "loadB"
}
Yes. Make an abstract getter in the parent class, and add implementation in children:
abstract class GenericDataManager<T> {
protected void saveData(Context context) {
String filePath = getFilePath();
}
protected void loadData(Context context) {
String filePath = getFilePath();
}
protected abstract String getFilePath();
}
public class ManagerA extends GenericDataManager<A> {
#Override protected String getFilePath() {
return "fileA";
}
}
I'm implementing a class that is responsible for all my HTTP requests from the Blackberry. I have around 10 or so screens that use this class to query a web service and get data from it. What would be the standard pattern to use in this case?
Currently I have it setup as follows -
public class NetworkAccessClass
{
public NetworkAccessClass(String url, String methodName, Vector paramNames, Vector paramValues, MainScreen screen) {
// perform inits
}
public void run() {
// Get Data
if(screen.instanceOf(LoginScreen)) {
((LoginScreen) screen).requestSucceded(responseData);
}
// So on for all 10 screens.
catch() {
((LoginScreen) screen).requestFailed(errorCode);
// So on for all 10 screens.
}
}
}
It works, but doesn't look right, and if a single screen has multiple types network requests, I'm being forced to add a flag to keep track of which function it's supposed to call back.
Is there a better way to do this?
Thanks,
Teja.
Use a callback interface, e.g. ResponseHandler:
public class NetworkAccessClass
{
public interface ResponseHandler {
void requestSucceeded(ResponseData responseData);
void requestFailed(ErrorCode errorCode);
}
public NetworkAccessClass(
String url,
String methodName,
Vector paramNames,
Vector paramValues,
ResponseHandler responseHandler) {
// perform inits
}
public void run() {
// Get Data
try {
...
responseHandler.requestSuceeded(responseData);
catch() {
responseHandler.requestFailed(errorCode);
}
}
}
This hopefully decouples your NetworkAccessClass from knowing about all the screens. Then either your screens implement NetworkAccessClass.ResponseHandler or they pass an adapter handler (anonymous inner class) to call the proper methods on the screen, e.g.
class LoginScreen {
...
new NetworkAccessClass(url, methodName, paramNames, paramValues,
new ResponseHandler() {
#Override
void requestSucceeded(ResponseData responseData) {
LoginScreen.this.handleLoginSuccess(responseData);
}
#Override
void requestFailed(ErrorCode errorCode) {
LoginScreen.this.handleLoginFailure(errorCode);
}
}
...
}
You could use a listener, which is a simple interface the network class would call back whenever something interesting happens :
public interface NetworkListener {
void requestSucceeded(byte[] responseData);
void requestFailed(int errorCode);
}
public class NetworkAccess {
// ...
public void run() {
// Get Data
if (successful) {
fireSucess(responseData);
}
catch(SomeException e) {
fireFailure(errorCode);
}
}
public void addNetworkListener(NetworkListener listener) {
// add listener to list of listeners
}
private void fireSuccess(byte[] responseData) {
for (NetworkListener l : listeners) {
l.requestSucceeded(responseData);
}
}
// ...
}
public class LoginScreen {
private void foo() {
NetworkAccess access = new NetworkAccess(...);
access.addNetworkListener(new NetworkListener() {
public void requestSucceeded(byte[] responseData) {
// do what you want
}
public void requestFailed(int errorCode) {
// do what you want
}
});
}
}
This is known as the Observable/observer pattern. The observable notifies its observers when something happens, but without having to know their exact type. The listsner class decouples the two parties.
I am new to android/java and currently am trying to learn custom events and listeners. I currently have this code implemented below that is working successfully. I now would like to add another event to DataRobot. The event will trigger when a certain piece of data is analyzed with the analyzeData function. I was wondering if someone could show me how to implement two events in that one class? I am using this event to trigger an AlarmDialog. So, if there is a better way, let me know.
/* SmartApp.java */
public class SmartApp extends Activity
{
private ConnectDevice cD = new ConnectDevice();
private DataRobot dR = new DataRobot();
private DataBuilder dB = new DataBuilder();
private DataSender dS = new DataSender();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.intro);
cD.addDataReceivedListener(new DataReceivedListener() {
#Override
public void dataReceivedReceived(DataReceivedEvent event) {
// TODO Auto-generated method stub
dR.analyzeData(event.getData());
}
});
dR.addDataAnalyzedListener(new DataAnalyzedListener() {
#Override
public void dataAnalyzedReceived(DataAnalyzedEvent event) {
// TODO Auto-generated method stub
dB.submitData(event.getData());
}
});
dB.addDataBuilderListener(new DataBuilderListener() {
#Override
public void dataBuilderReceived(DataBuilderEvent event) {
// TODO Auto-generated method stub
dS.sendData(event.getData());
}
});
}
}
/* DataRobot.java */
public class DataRobot {
/* This class is for analyzing the data */
private List _listeners = new ArrayList();
private String data;
public boolean analyzeData(String temp) {
/* Analyze the data
* This function analyzes the data, as explained in the OP
* This function fires the analyzed data event when finished
* analyzing the data.
*/
data = temp;
fireDataAnalyzedEvent(data); // this fires the dataanalyzedevent
return true; //for now this will always return true
}
public synchronized void addDataAnalyzedListener(DataAnalyzedListener listener) {
_listeners.add(listener);
}
public synchronized void removeDataAnalyzedListener(DataAnalyzedListener listener) {
_listeners.remove(listener);
}
private synchronized void fireDataAnalyzedEvent(String temp) {
DataAnalyzedEvent dRE = new DataAnalyzedEvent(this, temp);
Iterator listeners = _listeners.iterator();
while(listeners.hasNext()) {
((DataAnalyzedListener)listeners.next()).dataAnalyzedReceived(dRE);
}
}
public interface DataAnalyzedListener {
public void dataAnalyzedReceived(DataAnalyzedEvent event);
}
}
/* DataReceivedEvent.java */
public class DataReceivedEvent extends EventObject{
private String data;
public DataReceivedEvent(Object source, String temp) {
super(source);
// TODO Auto-generated constructor stub
data = temp;
}
public String getData() {
// this function is just an accessor function
return data;
}
}
/* DataAnalyzedEvent.java */
public class DataAnalyzedEvent extends EventObject{
private String data;
public DataAnalyzedEvent(Object source, String temp) {
super(source);
// TODO Auto-generated constructor stub
data = temp;
}
public String getData() {
// this function is just an accessor function
return data;
}
}
I would redesign in Android. Use a service and just register it to receive Intents with certain action types. Look at it this way: Intent is your event. Intent Filter is your Intent mapping, and event manager is by calling context.startActivity(Intent) or by broadcasting the Intent (pub/sub eventing) thats the Android way.
How you add a second event depends on if the two events are related. If an object will want to listen to both events, then it is as simple as adding another method to your DataAnalyzedListener interface.
The other case is where the events are not related and objects will want to subscribe to one event OR the other. In this case you will want to make two separate interfaces and have two listener lists.
Other Comments:
Use a parametrized list instead of the bare type and you won't need to cast the object.
Also you can use a foreach loop instead of grabbing the iterator directly.
private List<DataAnalyzedListener> _listeners = new ArrayList<DataAnalyzedListener>();
for (DataAnalyzedListener listener : _listeners) {
listener.dataAnalyzedReceived(dRE);
}