I'm working in an app using Parse.com and I've been experiencing some random behavior, I made a simpler version of my code to show you and while it keeps being random (the results I expect happen about 4 in 5 times) it got better (in my code it's correct about 2/5 of the runs).
So the method is this, a very simple creation and filling of a new object:
public void test(){
final List<ParseObject> list = new ArrayList<>();
for(j=0;j<4;j++){
list.add(new ParseObject("Object"));
list.get(j).put("Column1", "sup");
list.get(j).put("Column2", "bro");
if(j==3){
ParseObject.saveAllInBackground(list, new SaveCallback() {
#Override
public void done(ParseException e) {
Toast.makeText(MainActivity.this, "NANANANANANANANA BATMAN!",Toast.LENGTH_LONG).show();
}
});
}
}
}
}
Problem is it creates 4 ParseObjects (as it should) only 4/5 of the tries, then 1/4 it's only 3. Why does this happen?
Why don't you create and store your ParseObject in a variable and then, use put("Column1", "sup"); and put("Column2", "bro"); on it before adding this variable directly to your list? because you are accessing your list two times for nothing where it can be avoided.
It would be cleaner and it would allow you to debug better.
Related
I'm developing the chatting application using the SendBird SDK in android studio.
How can I get the list of Open Channels more than 1000?
You can create use an OpenChannelListQuery to traverse through your list of channels in fixed chunks.
OpenChannelListQuery query = OpenChannel.createOpenChannelListQuery();
query.setLimit(30);
query.next(new OpenChannelListQuery.OpenChannelListQueryResultHandler() {
#Override
public void onResult(List<OpenChannel> list, SendBirdException e) {
if (e != null) {
// Error!
}
// list contains the first 30 channels.
}
});
As long as your query instance is the same, you can call query.next() until you obtain as many channels as you want.
query.next(new OpenChannelListQuery.OpenChannelListQueryResultHandler() {
#Override
public void onResult(List<OpenChannel> list, SendBirdException e) {
// list contains the next 30 channels.
}
});
Edit: I forgot to mention that the first query.next() must be completely finished before you can call query.next() again. That is, make sure the first onResult() is called before calling query.next() again.
hello every one hope you having a nice day
in order to load tons of markers (like 1mil) i am passing a list of MapPos to a VectorDataSource and trying to force it to live create the Points whenever related coordinates must be visible to the map now , but unfortunanly after a few try seems i dont know much about the map . would you please help me solve this puzzle ? thaanks alot
public static void createlustering(Projection proj,MapView mapView,Context context,final Bitmap bmp,float distance,float textSize,final ArrayList<MapPos> points){
AbstractVectorDataSource<Geometry> source = new AbstractVectorDataSource<Geometry>(proj) {
#Override
public Collection<Geometry> loadElements(CullState arg0) {
//what to do here
return list;
}
#Override
public Envelope getDataExtent() {
//what to do here
return null;
}
};
// source.addAll(points);
Clusterer mClusterer = new Clusterer();
mClusterer.addPointCluster(mapView, context,source,bmp,distance,textSize);
}
Unfortunately, that's a bit of a large amount to load with clusters. A more scalable solution, however, is to load them to your CARTO account and query them from there (overviews are used).
cf. android samples: CartoDBSQLDataSource and CartoSQLActivity
Additionally, if you're open to upgrading your SDK version, you can check out newer samples (master branch)
So I have a Trip class and Place class that both extend ParseObject and have a many to many relationship between them. So I am using a ParseRelation like so:
Trip trip = ...
Place place = ...
trip.getRelation('place_relation').add(place);
trip.saveEventually();
Then, later on I fetch the places like so:
final ArrayList<Place> places;
ParseRelation<Place> placeParseRelation = trip.getRelation("place_relation");
ParseQuery<Place> placeParseQuery = placeParseRelation.getQuery();
placeParseQuery.findInBackground(new FindCallback<Place>() {
#Override
public void done(List<Place> objects, ParseException e) {
if (e != null) {
...
} else {
places = (ArrayList<Place>) objects;
}
}
});
I realize that because I'm using saveEventually() there might be a lag between when it is written to the db and fetching from the DB, but realistically it should be <1 sec for this to save properly. However I've found that it can take up to 5 minutes before the Places are returned in the query. It's quite variable how long it takes before the results show up, sometimes it is almost instant and, like I mentioned, sometimes it can be several minutes. I am on a fast internet connection using a new GenyMotion emulator.
Any ideas why this might be happening?
I hate using "sleepers" (Thread.sleep(millis)) in tests, but without sleepers some tests fail.
I have a ListView in my Android application and I want to tap on the first item in the list (SAUDI ARABIA in our case).
public AndroidDriver androidDriver;
...
androidDriver = new AndroidDriver(serverAddress, capabilities);
androidDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driverWait = new WebDriverWait(androidDriver, 30);
// at this moment everything is initialized and working properly,
// Appium server is up and running
driverWait.until(ExpectedConditions.visibilityOfElementLocated(By.id("com.###.debug:id/countries_list_view")));
WebElement countriesList = driver.findElement(By.id("com.###.debug:id/countries_list_view"));
List<WebElement> countries = countriesList.findElements(By.id("com.###.debug:id/list_item_container"));
WebElement country = countries.get(0);
// country isn't null, and it corresponds to a real ListView row
driverWait.until(ExpectedConditions.elementToBeClickable(country));
Thread.sleep(1000); // <---- country isn't clicked without this
country.click();
The same problem exists in Calabash/Cucumber tests (explicit waits required).
I've tried different ways of waiting for the element which should be clicked
driverWait.until(ExpectedConditions.visibilityOfElementLocated(By));
driverWait.until(ExpectedConditions.visibilityOf(WebElement));
driverWait.until(ExpectedConditions.elementToBeClickable(By));
driverWait.until(ExpectedConditions.presenceOfElementLocated(By));
and none is working. At the moment when I try to tap on the ListView 1st item, ListView exists and is all the list elements are on screen.
I've tried to find the ListView 1st row by getting the list row XPath using Appium Inspector. The result is the same - view isn't clicked without Thread.sleep.
Using Thread.sleep in tests is really bad practice and makes my tests unstable. I can't rely on tests results in this case, as they may fail even if the application is working properly. There's an article about "wait" and "sleep" usage in Selenium tests (Selenium WebDriver wait).
How to fix such issues in tests?
How often Thread.sleep calls used in automation world? (I'm mostly Android developer, and not that experienced in mobile automation).
UPDATE:
I've tried to not to mix up implicit and explicit waits, as JeffC mentioned, and it didn't help.
Here's my test:
#Test
public void selectCountryLanguageAndStartApplication() throws Exception {
countryLanguagePage.loaded();
countryLanguagePage.selectFirstCountry();
countryLanguagePage.pleaseSelectCountryTextIsHidden();
countryLanguagePage.startClick();
}
...
/**
* Verify the page has loaded
*/
public static void loaded() {
driver.findElement(By.id("com.###.debug:id/countries_list_view"));
}
I'm verifying if the page is loaded in every test. If I use only implicit waits - the test fails from time to time; if I use only explicit waits - it's the same, the test fails from time to time.
I've found in Appium tutorial that they use implicit in conjunction with explicit ones 1, 2. It looks weird according to the docs.
The working solution: I've modified a bit loaded method
public static void loaded() {
driver.findElement(By.id("com.###.debug:id/countries_list_view"));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Having that sleep brings the "stability" to test and I can find the elements and press on them with explicit waits or without them.
Does it mean, that I should add "sleep" when the new Activity launched (the only working solution to me)? Or I'm waiting for the Activity initialization in the wrong way?
You could try this:
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.elementToBeClickable(By));
or
while(!driver.findElement(By).isDisplayed())
{
//Thread.sleep(10);
}
I think Thread.sleep calls are fine to use (and almost necessary if your testing involves timing) but for the most part there a better ways to handle most things they would be used for.
Hope this helps,
Liam
I have Tried to write a method , to wait for an element. hope it will work for your case.
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class Utility {
public static AndroidElement element;
public static boolean isElementPresent;
public static boolean waitForPresence(AndroidDriver driver, int timeLimitInSeconds, String targetResourceId){
try{
element = (AndroidElement) driver.findElementByAndroidUIAutomator("new UiSelector().resourceId(\""+targetResourceId+"\")");
WebDriverWait wait = new WebDriverWait(driver, timeLimitInSeconds);
wait.until(ExpectedConditions.visibilityOf(element));
isElementPresent = element.isDisplayed();
return isElementPresent;
}catch(Exception e){
isElementPresent = false;
System.out.println(e.getMessage());
return isElementPresent;
}
}
}
I am working on an Android app which will support the Ice cream sandwich API but work on older devices such as running android 2.1.
I'm doing this by doing a check of what the current API version is, and if its post ice cream sandwich call one activity and then if its anything below, call a different activity.
I am allowing the user to perform a search, when it gets the results it then clears ArrayList and then adds the items from the search back in, and then calls the arrayadapter.notifydatasetchanged. This code I've copied and pasted from the ICS version into the pre ICS version, the ICS works fine but on the pre ics version the list view doesn't get updated. Below is the code that I have.
public void performSearch(ArrayList<Spanned> searchPasswords)
{
if (searchPasswords.size() > 0)
{
btnClearSearch.setVisibility(View.VISIBLE);
passwords.clear();
for (int i = 0; i < searchPasswords.size(); i++)
{
passwords.add(searchPasswords.get(i));
}
passwordArrayAdapter.notifyDataSetChanged();
btnClearSearch.setOnClickListener(mBtnClearSearch);
common.showToastMessage(searchPasswords.size() + " result(s) found", Toast.LENGTH_LONG);
}
else
{
common.showToastMessage("No search results found", Toast.LENGTH_LONG);
}
}
I've debugged this function so it is definetely calling it, and its displaying the toast messags with saying how many results were found, but the list view doesn't get changed.
Update
I have just made a discovery which is a bit confusing. As a test in the function that does the initial loading of the list view I manually create a new search ArrayList<Spanned> and pass this to the same PerformSearch(ArrayList<Spanned>) that I am having the problem with and this works without any problems.
The problem with the performSearch not updating the ListView only seems to happen when it is being called from onActivityResult. I know that onActivityResult is working fine as when the performSearch function is called it then prints out there is 1 result(s) found so its definitely got data just the list view doesn't get refreshed from the onActivityResult calling the performSearch function.
You can try:
passwordArrayAdapter = new WHAT_EVER_ADAPTER_THIS_IS(searchPasswords, extra_constructor_params);
YOUR_LIST_VIEW.setAdapter(passwordArrayAdapter)
instead of:
passwordArrayAdapter.notifyDataSetChanged();
I had a similar issue. Neither notidfyDataSetChanged() nor setAdapter() worked.
Finally I figured out a solution which may not be as efficient as using notifyDataSetChanged() but it works.
/**
* Updates courses' list adapter.
*/
private void updateListAdapter()
{
final ArrayAdapter a = (ArrayAdapter) coursesList.getAdapter();
runOnUiThread(new Runnable()
{
public void run()
{
populteCoursesList();
a.clear();
for (MainScreenListModel model : listModels)
{
a.add(model);
}
a.notifyDataSetChanged();
}
});
}
courseList is my custom list. populateCoursesList() gets the data from db and listModels is a Vector of models for list view.
As you can see I have to clear the adapter and fill it once again.
I think your mistake is to forget to clear the adapter, if you try it like this it should work:
public void performSearch(ArrayList<Spanned> searchPasswords)
{
if (searchPasswords.size() > 0)
{
btnClearSearch.setVisibility(View.VISIBLE);
passwordArrayAdapter.clear();
for (int i = 0; i < searchPasswords.size(); i++)
{
passwordArrayAdapter.add(searchPasswords.get(i));
}
passwordArrayAdapter.notifyDataSetChanged();
btnClearSearch.setOnClickListener(mBtnClearSearch);
common.showToastMessage(searchPasswords.size() + " result(s) found", Toast.LENGTH_LONG);
}
else
{
common.showToastMessage("No search results found", Toast.LENGTH_LONG);
}
}
passwords.clear();
for (int i = 0; i < searchPasswords.size(); i++)
{
passwords.add(searchPasswords.get(i));
}
passwordArrayAdapter.notifyDataSetChanged();
As per the code, u r modifying the list(passwords), but is it the same instance that is being used by the adapter (passwordArrayAdapter). If not then notifyDataSetChanged() wont work.
From my understanding, you can either set the list again with a new instance of passwordArrayAdapter.
ur_list_view.setAdapter(new PasswordArrayAdapter(newly_formed_password_list, and other parameters));
or use getter and setter to update the list(passwords) and then call notifyDataSetChanged()
I dont know much from only the code snippet you've pasted but from what I see there is no persistent link between passwords and the passwordsArrayAdapter....passwordsArrayAdapter initialises itself with the elements of passwords and passwordsArrayAdapter will not know when passwords changes. To add new items you should call passwordsArrayAdapter.add(searchPasswords).Dont bother calling notifyDataSetChanged() explicitly.
public void performSearch(ArrayList<Spanned> searchPasswords)
{
if (searchPasswords.size() > 0)
{
btnClearSearch.setVisibility(View.VISIBLE);
passwordArrayAdapter.clear();
passwordArrayAdapter.setNotifyOnChange(true);
for (int i = 0; i < searchPasswords.size(); i++)
{
passwordArrayAdapter.add(searchPasswords.get(i));
}
btnClearSearch.setOnClickListener(mBtnClearSearch);
common.showToastMessage(searchPasswords.size() + " result(s) found", Toast.LENGTH_LONG);
}
else
{
common.showToastMessage("No search results found", Toast.LENGTH_LONG);
}
}
I wouldnt think there'd be a relation with the onActivityResult bit -- the above code should fix it.
Call notifyOnChange(false) before clearing and adding the new entries. Otherwise, the clear() and every add() internally trigger a call to notifyDataSetChanged(), which, as I experienced, confuses the ListView. Keep your explicit notifyDataSetChanged(), which also resets the internal notifyOnChange flag to true again.
Thanks everyone for your help and suggestions, I've managed to find out what the problem was.
In my OnResume method for the activity I call a function called populateListArray which retrieves all of the information from the database and lists in the ListView.
When the activity was returned it was calling the OnResume method so after it got the results it then reset the list view back with all the original content.
To get round it I added a variable called performingSearch which I initialise to false. When I perform the search I set this to true and in the onResume, if the variable is true I don't do anything and after the perform search function has finished I set the variable back to false again.
Thanks everyone again for your help