I'm using the Parse library to query some records from DB that will be shown in a ListView with a custom adapter. I've a table with records and each record should I do a counting query from other table.
This is the thread for the counting query of each object retrieved:
getVisualizations = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < events.size(); i++) {
ParseQuery<ParseObject> query = ParseQuery.getQuery(ParseConstant.PT_VISUALIZ);
query.whereEqualTo(ParseConstant.PT_VISUALIZ_EVENTO, events.get(i));
events.get(i).setVisualizations(query.count());
}
}
});
events is an Object ArrayList
And this is the code in the main
ParseQuery<ParseObject> query = ParseQuery.getQuery(ParseConstant.PT_EVENT);
query.setLimit(30);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> resultList, ParseException e) {
if (e == null) {
events = new ArrayList<Event>();
for (int i = 0; i < resultList.size(); i++) {
Event event = (Event) resultList.get(i);
events.add(event);
}
if (!getVisualizations.isAlive()) {
getVisualizations.start();
}
if (adapter != null) {
adapter.notifyDataSetChanged();
} else {
adapter = new AdapterEvent(getActivity(), R.layout.list_event, events, list);
AnimationAdapter animAdapter = new SwingBottomInAnimationAdapter(adapter);
animAdapter.setAbsListView(list);
list.setAdapter(animAdapter);
}
loadingBar.setVisibility(View.INVISIBLE);
} else {
Log.d("score", "Error: " + e.getMessage());
}
}
});
The problem is that after the thread has started, I don't know how to block the main thread until the other thread finish. (Sorry for the english :/ )
perhaps you should use Thread.join() - if we are dealing with 2 threads, this will block one thread, while allowing the other to complete, then once it does complete, it will resume. Here is a tutorial on it
Related
I'm new to android and I need help in retrieving the array that I created in parse server named as "busStops" but I can't figure out where the problem exists in my code
ParseQuery<ParseObject> parseQuery = new ParseQuery<ParseObject>
("RouteDetails");
parseQuery.whereEqualTo("routeNumber",searchView.getText().toString());
parseQuery.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> busStops, ParseException e) {
if(e == null){
final List<String> arrayList = new ArrayList<>();
for (ParseObject parseObject : busStops){
if (parseObject.getList("busStops") != null) {
arrayList.add(parseObject.getList("busStops").toString());
}
}
arrayAdapter = new ArrayAdapter(SearchForRoutes.this,android.R.layout.simple_list_item_1,arrayList);
listView.setAdapter(arrayAdapter);
}
}
});
It is possible to show an Array in a ListView. You should use getJSONArray instead of getList in your JAVA code. See my code below.
My structure class is:
Then, I added the code below into my Activity (MainActivity.java):
final ListView listView = (ListView) findViewById(R.id.listviewA);
ParseQuery<ParseObject> query = ParseQuery.getQuery("RouteDetails");
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> results, ParseException e) {
if (e == null) {
for(int i = 0; i < results.size(); i++) {
JSONArray array = results.get(i).getJSONArray("busStop");
for(int j = 0; j < array.length(); j++) {
try {
dataList.add(array.getString(j));
} catch (JSONException e1) {
e1.printStackTrace();
}
}
myArray = dataList.toArray(new String[dataList.size()]);
ArrayAdapter<String> adapterList
= new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_single_choice, myArray);
listView.setAdapter(adapterList);
}
} else {
final Toast toast = Toast.makeText(
MainActivity.this,
String.valueOf("Error =>" + e.getMessage()),
Toast.LENGTH_LONG
);
toast.show();
}
}
});
And the result will be something like as this:
First of all, you may don't need to create another ArrayList than the list that is returned by parseObject.getList("busStops"). You can directly pass it to the adapter constructor. But since you may want to do a process on the list, iterate the list like :
for(Object s : parseObject.getList("busStops") { String current = s.toString(); }
Also you can save the list to another ArrayList by passing it to ArrayList constructor.
ArrayList<String> al = new ArrayList<>(parseObject.getList("busStops"))
And finally, you can fix your code (that is worst-practice :) ) by simply deleting the .toString() from the line in your none-null if statement and changing add to addAll.
like this : arrayList.addAll(parseObject.getList("busStops"));
I use Looper.prepare and Looper.loop in Runnable's run function. But the problem is that the thread not loop at all, the Runnable just run one time. In Activity1, I use three Runnable threads, all looping. Two threads get Data and pictures from net constantly through "while" loop(needn't update UI), one thread select data and pic from local sqlite constantly through "Looper". The data is:
protected void onCreate(Bundle savedInstanceState) {
......
new Thread(getMessageTask).start();
getMessageHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
i++;
System.out.println("niuanmata" + i); //one appear the first one
try {
ArrayList<Map<String, String>> listMessages = (ArrayList<Map<String, String>>)msg.obj;
boolean listchange = true;
if (oldMessages.size() != 0) {
if (listMessages.size() == oldMessages.size()) {
for (int i = 0; i < listMessages.size(); i++) {
Map<String, String> oldmessage = (Map<String, String>) oldMessages.get(i);
Map<String, String> newmessage = (Map<String, String>) listMessages.get(i);
if ((oldmessage.get("mID") != newmessage.get("mID")) || (oldmessage.get("mainContent") != newmessage.get("mainContent")) || (oldmessage.get("deadLine") != newmessage.get("deadLine"))) {
break;
}
if (i == (listMessages.size() - 1)) {
listchange = false;
}
}
}
}
if (listchange) {
SimpleAdapter adapter = new SimpleAdapter(MainActivity.this, listMessages, R.layout.layout_invites,
new String[]{"mID", "creater", "mainContent", "deadLine", "mtype", "createrLogo"},
new int[]{R.id.tv_list_type, R.id.tv_list_name, R.id.tv_list_inviteword, R.id.tv_list_invitedate, R.id.tv_list_inviteid, R.id.iv_list_logo});
lvMessage.setAdapter(adapter);
oldMessages = listMessages;
}
} catch (Exception e) {
Toast.makeText(MainActivity.this, "wrong: " + e.toString(), Toast.LENGTH_SHORT).show();
return;
}
}
};
......
lvMessage.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) { //when creater click, update the message; when others click, reset the alarm
Toast.makeText(MainActivity.this, "ok" , Toast.LENGTH_SHORT).show();
}
});
}
.........
Runnable synchroDataTask = new Runnable() {
#Override
public synchronized void run() {
//data syschno
while (IOHelper.loopjudge()) {
{
AccountsDB adb = new AccountsDB(MainActivity.this);
String thelastupdate = adb.getLastUpdate(account.getChatNO());
Calendar calendar = IOHelper.StringToCalendar(thelastupdate);
calendar.add(Calendar.MINUTE, -30);
String accountData = synchroDataWebservice(account.getChatNO(), IOHelper.CalendarToString(calendar)); //get the datas of the account synchroly
AccountBLL.saveDBofWebString(accountData, MainActivity.this, account); //use static method to save the DB string as SQLite data
}
}
.........
#Override
public synchronized void run() {
while (IOHelper.loopjudge()) {
......
}
.......
Runnable getMessageTask = new Runnable() {
#Override
public synchronized void run() {
Looper.prepare();
//while (IOHelper.loopjudge() && (!stopThread)) {
MessageDB messagedb = new MessageDB(MainActivity.this);
List<MessageMain> messages = messagedb.getMessageByChatNO(account.getChatNO());
ArrayList<Map<String, String>> listMessages = setMessaageListToMap(messages);
Message msg = Message.obtain();
msg.obj = listMessages;
getMessageHandler.sendMessageDelayed(msg, 1000);
//}
Looper.loop();
}
};
......
In my limited experience with android, I use while to do the Loop in getMessageTask , because the data and UI's listview need to be updated constantly. But the listview can not be clicked. Then change to Looper, but the the UI's listview can't be updated constantly....
The answer is that I misunderstand the meaning of Looper, think the Looper.prepare() and Looper.loop() as the while() loop, then make the mistake.
Looper.prepare() and Looper.loop() just means that this thread can be looped, but I must write while loop or for loop by myself.
I am trying to get records from parse. My table in parse contains an array of pointers; I was facing difficulties to write parse query, so I first save array of pointers in an ArrayList, now I make a for loop to execute the query; for each loop iteration, I want to get records from parse and update local db then same as for next iterations. But this is creating some different problems. parse getInBackground is not working sequentially.... my outer for loop completely executes then parse method called due to which I am facing problems to save values in local db.
public void insertGroupsInDB(ArrayList<TempGroupClass> temp)
{
Log.d(TAG,"insertGroupsInDB: temp size:"+temp.size());
for(int i = 0;i<temp.size();i++) `//my target is to make inner query run till no of loop times and for each iterations inner parse query will run and then insert records in db against outer insertion group`
{
Groups grp = new Groups();
grp.setGroupTitle(temp.get(i).getGroupTitle());
grp.setGroupType(temp.get(i).getGroupType());
grp.setParseObjectId(temp.get(i).getParseObjectId());
long groupinsert = (YouinDatabase.getInstance(context)).addGroup(grp,context);
//}
/*try
{
final CountDownLatch latch = new CountDownLatch(1);*/
if(groupinsert != -1)
{
//now insert friends
//long friendInsertId = YouinDatabase.getInstance(context).addFriend();
//now get friends from members id
Log.d(TAG,"groups inserted successfully:"+groupinsert);
final ArrayList<Integer> list = new ArrayList<Integer>();
if(temp.get(i).getFriendObjectIdList().size() > 0)
{
for(int j =0;j<temp.get(i).getFriendObjectIdList().size();j++)
{
Log.d(TAG," >>>>>>>>>>>>>>>friend objectId>>>>>>>>>>>>>>:"+temp.get(i).getFriendObjectIdList().get(j));
ParseQuery<ParseUser> query = ParseUser.getQuery();
query.whereContainedIn("objectId",temp.get(i).getFriendObjectIdList());
query.findInBackground(new FindCallback<ParseUser>() {
#Override
public void done(List<ParseUser> arg0,
ParseException arg1) {
// TODO Auto-generated method stub
if(arg1 == null)
{
//Log.d(TAG,"arg0 size:"+arg0.size());
if(arg0.size() >0)
{
for(int i = 0;i<arg0.size();i++)
{
Log.d(TAG,"arg0.size():"+arg0.size());
Friend f = new Friend();
f.setUsername(arg0.get(0).getString("username"));
f.setParseObjectId(arg0.get(0).getObjectId());
f.setHasAdded(false);
boolean userAlreadyExist = YouinDatabase.getInstance(context).checkUserExistInFriendTable(arg0.get(0).getString("username"));
long friendInsertId = -1;
ArrayList<Integer> list = new ArrayList<Integer>();
int friendid;
if(!userAlreadyExist)
{
// Log.d(TAG,"friend Already not exist :"+userAlreadyExist);
friendInsertId = YouinDatabase.getInstance(context).addFriend(f);
list.add(YouinDatabase.getInstance(context).findFriendIdOfLatestRecord());
friendid = YouinDatabase.getInstance(context).findFriendIdOfLatestRecord();
}
else
{
//Log.d(TAG,"friend Already exist :"+userAlreadyExist);
//list.add(YouinDatabase.getInstance(context).getFriendIdFromFriendName(arg0.get(0).getString("username")));
friendid = YouinDatabase.getInstance(context).getFriendIdFromFriendName(arg0.get(0).getString("username"));
}
// Log.d(TAG,"list size 1 :"+list.size());
int latestGroupInsertId = YouinDatabase.getInstance(context).findGroupIdOfLatestRecord();
long id = YouinDatabase.getInstance(context).addFriendInConnection(friendid,latestGroupInsertId);
//now update user setHasAdded
long updateFriendTable = -1;
if(id != -1)
{
updateFriendTable = YouinDatabase.getInstance(context).updateFriendTable(friendid);
}
Log.d(TAG,">>>>updated friend id information:>>>>");
if(updateFriendTable != -1)
{
Friend friendDetails = YouinDatabase.getInstance(context).getFriendDetailsFromFriendId(friendid);
Log.d(TAG,"friend name:"+friendDetails.getUsername());
Log.d(TAG,"friend:"+friendDetails.getParseObjectId());
Log.d(TAG,"friend added :"+friendDetails.isHasAdded());
Log.d(TAG,"groupId:"+latestGroupInsertId);
}
//YouinDatabase.getInstance(context).get
}
Log.d(TAG,"list size 2"+list.size());
}
}
else
{
Log.d(TAG,"arg1 != null:"+arg1.getMessage());
}
}
});
}
// Log.d(TAG,"list size:"+list.size());
}
//latch.countDown();
}
/*latch.await();
}
catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
}
Right now, the problem is that my outer loop executes twice one after another and then after the loop ends, then my parse method brings data from parse ...due to which it's only updating record in db against last group id ...and it's not inserting records against first groupId
How to resolve this issue? I have used this technique because I failed to write query to get object result of array of pointers using parse.
You could use find() which should do a synchronous operation which might hold up your ui. I have not used parse yet so i dont know. Or you can set up something like below. Remove the outer and check conditions in your callback to determine when to launch the next query.
private int j = 0;
private int loopnumber = temp.size();
ArrayList<TempGroupClass> temp; //setup temp somewhere else
private void doQuery() {
ParseQuery<ParseUser> query = ParseUser.getQuery();
query.whereContainedIn("objectId",temp.get(i).getFriendObjectIdList());
query.findInBackground(new FindCallback<ParseUser>() {
#Override
public void done(List<ParseUser> arg0,
ParseException arg1) {
// TODO Auto-generated method stub
if(arg1 == null)
{
...
...
else
{
Log.d(TAG,"arg1 != null:"+arg1.getMessage());
}
//at the end call the same method to start a query if the loop conditions have not been reached.
if(++i < loopnumber) {
doQuery();
}
}
});
}
}
I have to fetch some data from the parse cloud. I'm using the parse sdk for android. How do I call the method findInBackground asynchronously in my activity? Essentially, where do I place this piece of code in my Activity? Below is my code:
ParseQuery<ParseObject> query = ParseQuery.getQuery("Average");
query.whereEqualTo("squarefeet", area);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
if (objects.size() > 0) {
for (int i = 0; i < objects.size(); i++) {
ParseObject p = objects.get(i);
averageConsumption = p
.getNumber("average_consumption");
efficientConsumption = p
.getNumber("efficient_consumption");
}
}
} else {
// something went wrong!
}
}
});
I called it inside an OnClick method of an OnClickListener. This made it asynchronous! Pretty silly but works! Previously I called it synchronously in OnCreate.
i have around 13000 records on one table(HashTag -classname) . i want to retrieve all of them on a single query. but parse allows only 1000 per query. any other ways get the all the records..
ParseQuery<ParseObject> query = ParseQuery.getQuery("HashTag");
query.whereExists("Tag"); query.orderByAscending("Type"); query.setLimit(1000);
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> list,
ParseException e) {
// TODO Auto-generated method stub
if (e == null)
{
if (list.size() > 0) {
for (int i = 0; i < list.size(); i++) {
ParseObject p = list.get(i);
String tagid = p.getString("Tag");
String Type = p.getString("Type");
class2 c2 = new class2();
c2.type = "" + Type;
c2.tag = "" + tagid;
listClass2.add(c2);
}
}
Sure, you can run multiple queries on the same table, with query's skip property incremented by 1000 each time:
Get the total number of records via query.count(), and use it to set a 'skip' variable
Run a new query for each 1000 records, updating your skip property accordingly
Process records as normal when each query returns
Something like this:
ParseQuery<ParseObject> query = ParseQuery.getQuery("HashTag");
query.whereExists("Tag");
query.countInBackground(new CountCallback() {
public void done(int count, ParseException e) {
if (e == null) {
// The count request succeeded. Run the query multiple times using the query count
int numQueries = Math.ceil(count / 1000); //Gives you how many queries to run
for(int skipNum = 0; l < numQueries; l++){
ParseQuery<ParseObject> query = ParseQuery.getQuery("HashTag");
query.whereExists("Tag"); query.orderByAscending("Type");
query.setLimit(skipNum * 1000);
query.findInBackground(new FindCallback<ParseObject>() {
//Run your query as normal here
}
}
} else {
// The request failed
}
}
//Declare a global variable for storing the complete data
private static List<ParseObject>allObjects;
allObjects=new ArrayList<ParseObject>();
ParseQuery<ParseObject>query3=ParseQuery.getQuery("HashTag");
query3.whereExists("Tag");
query3.setLimit(1000);
query3.findInBackground(getallobjects());
int limit=1000;
int skip=0;
//callback method:
private FindCallback<ParseObject>getallobjects(){
return new FindCallback<ParseObject>(){
#Override
public void done(List<ParseObject>list,ParseException e){
allObjects.addAll(list);
if(list.size()==limit){
skip=skip+limit;
ParseQuery<ParseObject>query=ParseQuery.getQuery("HashTag");
query.setSkip(skip);
query.setLimit(limit);
query.findInBackground(getallobjects());
}else{
//you have full data in allobjects
for(int i=0;i<allObjects.size();i++){}
}
}}}
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("TestObject");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> list, ParseException e) {
for(ParseObject p : list){
Log.d("--", (String) p.get("foo")+p.getCreatedAt());
}
}
});