Return value inside Facebook request OnComplete - android

My doubt is, when i call a method below, the value is null, of course, because the object user it's not already populated, because will be populated inside Facebook request. So, the question is, how can i wait for the facebook complete and then return the right arraylist of users?
public ArrayList<User> getUsers(){
ArrayList<User> users = new ArrayList<User>();
User user = new User();
//It's not the complete code
Facebook.resquest(){
#Override
onComplete(){
for(int i = 0;i<10;i++){
users.add(user)
}
}
}
// The question is, what do i have to do for the below object 'll have the same value of user object inside facebook request?
return users;
}

Use Request.executeAndWait(request);
in your code, before the return.

Related

fetch the data from firebase and populate the recyclerview through for loop if the keys of the node are stored locally [duplicate]

Basically what I am trying to do is I have a database with the name users having an attribute username. I have some usernames in one list and I want to show details of these users only whose username is present in the list. How can I write a query to fetch details of those users only whose username is found in this list? And note that there is no lexicographical ordering so i can't use startAt() and endAt() functions as well.
code snippet:
=> myList contains usernames. This code doesn't yield accurate results.
Any help would be really appreciated! Thank you!
FirebaseRecyclerOptions<MainModel> options =
new FirebaseRecyclerOptions.Builder<MainModel>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("users").orderByChild("username")
.startAt(myList.get(0)).endAt(myList.get(myList.size()-1)),MainModel.class).build();
As already mentioned in the comment, the Firebase-UI library doesn't help in your case, because it doesn't allow you to pass multiple queries to the FirebaseRecyclerOptions object. So you need to perform a separate query and use the combined result.
When you are calling .get() on a Firebase Realtime Database query object, you are getting back a Task object. So the key to solving this problem is to use whenAllSuccess(Collection> tasks). In your case, it should look like this:
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference usersRef = db.child("users");
Query query = usersRef.orderByChild("username");
List<Task<DataSnapshot>> tasks = new ArrayList<>();
for (String username : myList) {
tasks.add(query.equalTo(username).get());
}
Tasks.whenAllSuccess(tasks).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
#Override
public void onSuccess(List<Object> list) {
//Do what you need to do with your list.
for (Object object : list) {
MainModel mm = ((DataSnapshot) object).getValue(MainModel.class);
if(mm != null) {
Log.d("TAG", mm.getUsername());
}
}
}
});
Assuming that you have in your MainModel class a getter called getUsername(), the result in your logcat will be all the usernames of all returned children.

Do I stuck in Looper.java?

I have a JsonObjectRequest Get Method (volley), it was working fine, I got an JsonObject and used it for further actions but now it doesn't do what I want..
In the same class like the Get Request, I have the Method processResponse, which creates an "Account" Object and adds it to the Manager List:
private void processResponse(JSONObject response) {
try {
Log.e("processResponse", " called");
final Account user = new Account("","","");
String username = response.getString("Username");
String email = response.getString("Email");
String id = response.getString("Id");
user.setUsername(username);
user.setEmail(email);
user.setId(id);
Manager.AddObjectToUserList(user);
Manager Class with List:
class Manager {
private static List<Account> _ListofUsers = new ArrayList<Account>();
static void AddObjectToUserList(Account acc)
{
_ListofUsers.add(acc);
}
List<Account> getListOfUsers(){
return _ListofUsers;
}
}
I get an JsonObject from the GetResponse, it does successfully process the Response and creates an Object but when i want to return the List in Manager to another class, the "return List" is 0, I don't get the problem, since it was working fine before.
In debug mode, it jumps after the return List into the Looper.java and it doesn't leave this class..
This is happening because of asynchronous behaviour. You are trying to add the object to list after you are creating the list, that's why you are getting 0. If you want to use that list, you need to use it in processResponse method. Please see also this post
Hope it helps.

Android Firebase code organization (concept)

I'm developing my first android app using Firebase. It is also my first android app overall, so I'm not expirienced, but already got some expirience with programming lanugages such as Java or PHP. I'm searching for professional advice since I've run into some problems with my code organization. I already did some research but was not able to find a good solution for this.
My app uses Firebase Authentication and Firebase Realtime Database.
I'm going to explain all relevant parts for my problem.
The main activity...
Checks if a user is logged in, if not, start the authentication activity
Contains a Object DatabaseHandler, which is responsible for the database access, this object needs a UserInfo object to be instantiated
Contains a FirebaseAuth object attached with a AuthStateListener
This AuthStateListener check if a user is logged in, if so it will re-instantiate the DatabaseHandler object with the current user
Should be able to display some data retrieved from the DatabaseHandler
My problem
I already need to have access to the DatabaseHandler object in the onCreate() method of the MainActivity to display some data, but since the DatabaseHandler gets instantiated in the method onAuthStateChanged(), to make sure there is already a user logged in, this does not work, because onCreate() is called before onAuthStateChanged()
My thoughts
I'm not entirely sure how to solve this problem, but my first thought was to restructure my project in a way that my main activity only checks which activities to call, instead of displaying data on it's own. I'm still in the early phase of the project, so this should not be much of a problem.
Just wanted to know if this will work or if there is any better solution to this.
Let me know what you think
Here an example of the activity with code that assumes you want to display a List of Books:
public class MainActivity extends AppCompatActivity {
private List<Book> bookList = new ArrayList<>();
private RecyclerView recyclerView;
private BookAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
adapter = new BookAdapter(bookList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
FirebaseAuth auth = FirebaseAuth.getInstance();
FirebaseUser user = auth.getCurrentUser();
if (user != null) {
// User is still logged in
// Get UserInfo and instantiate DatabaseHandler
populateList();
} else {
// No user is logged in, go to auth activity
}
}
private void populateList() {
// Get Books from Firebase and add them to the adapter
Book book = new Book();
bookList.add(book);
// Notify the adapter, so that it updates the UI
adapter.notifyDataSetChanged();
}
}
With this you do the following:
create and instantiate all objects in onCreate
check for user in onCreate and act accordingly
get Data and display it from populateList, which allows to re-populate the list without going through all of the onCreate stuff (remember to clear the list/adapter

Point Backendless object to user [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I'm migrating to Backendless from Parse and is currently trying to do something that was pretty obvious with Parse.
I'm creating a class:
#ParseClassName("UserPreferences")
public class UserPreferences extends ParseObject {
public ParseFile getBackground(){
return getParseFile("background.jpg");
}
public boolean getAudioStatus(){
return getBoolean("audio");
}
public void setAudioStatus(boolean status){
put("audio", status);
}
}
Now I want to assign this class to the currently logged in user as a pointer:
UserPreferences userPrefs = new UserPreferences();
userPrefs.setAudioStatus(true);
ParseUser user = ParseUser.getCurrentUser();
user.put("prefs", userPrefs);
userPrefs.saveInBackground()
user.saveInBackground(); //again, use SaveCallback
and to retrieve all values etc to be applied to local preferences:
ParseUser user = ParseUser.getCurrentUser();
UserPreferences userPrefs = user.getParseObject("prefs");
userPrefs.fetchInBackground();
This way, the user's data is always tied to himself and objectID etc isn't a problem.
Now I didn't work this out myself when using Parse. So unfortunately I can't really talk for this matter. I just hope someone more experienced see's what I'm doing and can relate this into translating it to Backendless SDK and workflow somehow?
You do not need to extend any specialized Backendless classes in the objects you save/load to/from Backendless. In the classes you can use either public fields or getter/setter properties. You do not need to use any annotations. Things are much simpler. If you have a class A which references class B (via a field or a javabean property), then on the backend, we will store A in a table called "A" and B in a table called "B". We will also create a relation between the two records on the backend.
There are two ways you could handle what you showed with Backendless:
Saving user object with preferences:
BackendlessUser user = Backendless.UserService.CurrentUser();
user.setProperty( "audioStatus", true );
user.setProperty( "backgroundImageUrl", url-to-background-jpg );
Backendless.UserService.save( user, asyncCallback );
This will result in creating two columns in the Users table: "audioStatus" and "backgroundFile". If, however, you want to have a separate table where all the preferences are, you could do this:
public class UserPreferences
{
// or use Java bean getter/setter instead of fields
public String backgroundImageUrl;
public boolean audioStatus;
}
UserPreferences prefs = new UserPreferences();
prefs.backgroundImageUrl = url-to-background-jpg;
prefs.audioStatus = true;
BackendlessUser user = Backendless.UserService.CurrentUser();
user.setProperty( "userPrefs", prefs );
Backendless.UserService.save( user, asyncCallback );
This will result in a secondary table created on the backend. The table will be called "UserPreferences" - just like the class name. Backendless will also create a relationship between the user object and the specific record in the UserPreferences table.
Retrieving user properties
If the user properties are not stored via a relation (see the first sample above), then they are loaded right away when the user logs in. Then you can get the properties with the getProperty method:
Backendless.UserService.login( userName, password, new AsyncCallback<BackendlessUser>()
{
#Override
public void handleResponse( BackendlessUser user )
{
boolean audioStatus = (boolean) user.getProperty( "audioStatus" );
String fileUrl = (String) user.getProperty( "backgroundImageUrl" );
}
#Override
public void handleFault( BackendlessFault backendlessFault )
{
}
});
If the preferences are stored in a related table, then you have several options to load them:
BackendlessUser user = Backendless.UserService.CurrentUser();
ArrayList<String> relations = new ArrayList<String>();
relations.add( "userPrefs" ); // name of the relation column in Users
Backendless.Data.of( BackendlessUser.class ).loadRelations( user, relations, new AsyncCallback<BackendlessUser>()
{
#Override
public void handleResponse( BackendlessUser user )
{
// user - object with loaded relations.
// now you can do this:
UserPreferences prefs = (UserPreferences)user.getProperty( "userPrefs" );
}
#Override
public void handleFault( BackendlessFault backendlessFault )
{
}
});
Hope this helps!

Refresh context in Android

I don't know if I understand the problem correctly, but I have a weird issue. I have list which I am getting from Parse.com server and I filter the data by "tags". Sometimes I change "tags" with DialogFragment and refresh the lists, but after 2-3 change the list is showing wrong data. I have debugged it and it seems that wrong data is being taken from Database, which is weird because in another Fragment window the same method returns correct answers.
Here is how I get list from Parse :
YoursEventsAsync yoursEventsAsync = new YoursEventsAsync(Constants.LIMIT, getActivity());
yoursEventsAsync.asyncResponse = this;
yoursEventsAsync.execute();
Then, in this AsyncTask I am getting data like this :
#SafeVarargs
#Override
protected final ArrayList<Event> doInBackground(ArrayList<Event>... params) {
return ParseAdapter.getInstance().getEventsFromServer(limit, context);
}
And this is my main function responsible for getting sometimes good sometimes bad data :
public ArrayList<Event> getEventsFromServer(int limit, Context context) {
ParseQuery<ParseObject> query = ParseQuery.getQuery("Event");
query.whereContainedIn("tags", DatabaseAdapter.getTagNames(context));
query.setLimit(limit);
query.include("createdBy");
query.orderByDescending("createdAt");
ArrayList<Event> events = new ArrayList<>();
try {
List<ParseObject> parseEvents = query.find();
events = setEventList(parseEvents);
} catch (ParseException e) {
e.printStackTrace();
}
return events;
}
I have debugged the 3rd line and it sometimes works fine and sometimes not.
Here is DatabaseAdapter.getTagNames method :
public static List<String> getTagNames(Context context) {
Realm realm = Realm.getInstance(context);
RealmQuery<Tag> query = realm.where(Tag.class);
RealmResults<Tag> tagResults = query.findAll();
List<String> tags = new ArrayList<>();
for (Tag tag : tagResults) {
tags.add(tag.getName());
}
return tags;
}
As I have said earlier, if I open another fragment, which uses the same method 'getTagNames' it works fine. That's why I think the problem is with context. Is it possible that AsyncTask is somehow remembering the context and retrieveing the old one?

Categories

Resources