How to force an async task to wait for answer? - android

I'm using an asynchronus library to get the weather forecast, but my code still goes on even if I haven't receive the informations about the weather. Is there any way to wait for the answer ? Or do you know anything that could help me with that ?

The code goes on is fine. You should using callback to receive data. For more detail, please attach your function.

WeatherClass.java
public class WeatherClass {
private static double temp = 0.0;
public static double getTemp(double latitude, double longitude, Context context){
String OPEN_WEATHER_MAP_API = "xxxxxxxxx";
new WeatherManager(OPEN_WEATHER_MAP_API).getFiveDayForecastByCoordinates(latitude,longitude,
new WeatherManager.ForecastHandler() {
#Override
public void onReceivedForecast(WeatherManager manager, Forecast forecast) {
// Handle forecast
List<Double> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
long timestamp = forecast.getTimestampByIndex(i+3);
Weather weatherForTimestamp = forecast.getWeatherForTimestamp(timestamp);
Temperature tempMini = weatherForTimestamp.getTemperature().getMinimum();
double temperatureInCelcius = tempMini.getValue(TemperatureUnit.CELCIUS);
list.add(temperatureInCelcius);
Log.v("Weather", "" +weatherForTimestamp.getWind().getSpeed());
Log.v("Weather", "Température mini : " + " "+ list.get(i));
}
int minIndex = list.indexOf(Collections.min(list));
Log.v("Weather MINI", "Température mini : " + list.get(minIndex));
//Toast.makeText(context, "Température mini: " + list.get(minIndex), Toast.LENGTH_LONG).show();
temp = list.get(minIndex);
Log.v("WeatherClass", temp + "");
}
#Override
public void onFailedToReceiveForecast(WeatherManager manager) {
Log.v("TAG", " ERREUR");
temp = -1000000;
}
}
);
return temp;
}
}

Your code run:
Create a request to get data.
Return temp = 0.0
Receive data from server and update temp.
So you run your code will get return value = 0.0.
To fix it, you can do:
Create new Interface.
IResult.java
public interface IResult {
void onResult(double temp);
}
Update getTemp method:
public static void getTemp(double latitude, double longitude, final IResult callback){
String OPEN_WEATHER_MAP_API = "xxxxxxxxx";
new WeatherManager(OPEN_WEATHER_MAP_API)
.getFiveDayForecastByCoordinates(latitude,longitude,
new WeatherManager.ForecastHandler() {
#Override
public void onReceivedForecast(WeatherManager manager, Forecast forecast) {
// Handle forecast
List<Double> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
long timestamp = forecast.getTimestampByIndex(i+3);
Weather weatherForTimestamp = forecast.getWeatherForTimestamp(timestamp);
Temperature tempMini = weatherForTimestamp.getTemperature().getMinimum();
double temperatureInCelcius = tempMini.getValue(TemperatureUnit.CELCIUS);
list.add(temperatureInCelcius);
Log.v("Weather", "" +weatherForTimestamp.getWind().getSpeed());
Log.v("Weather", "Température mini : " + " "+ list.get(i));
}
int minIndex = list.indexOf(Collections.min(list));
Log.v("Weather MINI", "Température mini : " + list.get(minIndex));
//Toast.makeText(context, "Température mini: " + list.get(minIndex), Toast.LENGTH_LONG).show();
temp = list.get(minIndex);
Log.v("WeatherClass", temp + "");
callback.onResult(temp);
}
#Override
public void onFailedToReceiveForecast(WeatherManager manager) {
Log.v("TAG", " ERREUR");
temp = -1000000;
callback.onResult(temp);
}
}
);
}
Use it
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WeatherClass.getTemp(32.32, 322.3, new IResult() {
#Override
public void onResult(double temp) {
//result here
}
});
}
Update: Because the first launch, this method return 0.0 before updating temp (step 2 return temp, step 3 update temp), so you will get 0.0. The second launch, this method will return the result of first launch (because it return temp before updating temp), so you may think it right (but not right, return value is data of the first launch) .

Related

How can I have a delayed (with Undo) Swipe to Delete Recyclerview that uses Room and LiveData?

I implemented a swipe-to-delete feature in my app using the following sample as a guide nemanja-kovacevic/recycler-view-swipe-to-delete. Initially I was using a simple SQLite Database class and everything was working correctly.
In attempting to update my app to utilize Android's Architecture Components Room and LiveData, I followed Google's Room with a view Codelab. After updating the code, it seemed to work, and does for a single swipe. However, if you swipe another row before the Undo delay completes, LiveData updates the adapter's cached copy of the List so that the subsequent pending removal runnables can't find the item they are supposed to move in the list (position=-1), which crashes the app.
That was a lot of explanation, here is the Adapter Code:
public class DropsListAdapter extends RecyclerView.Adapter<DropsListAdapter.DropHolder> {
private final static int PENDING_REMOVAL_TIMEOUT = 3000; // 3sec
private final LayoutInflater inflater;
private Context context;
private Handler mHandler = new Handler();
private HashMap<DeadDrop, Runnable> pendingRunnables = new HashMap<>();
private List<DeadDrop> deadDrops;
private List<DeadDrop> dropsPendingRemoval;
DropsListAdapter(Context context) {
inflater = LayoutInflater.from(context);
this.context = context;
this.dropsPendingRemoval = new ArrayList<>();
}
#NonNull
#Override
public DropHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new DropHolder(inflater.inflate(R.layout.drop_list_item, parent, false));
}
#Override
public void onBindViewHolder(#NonNull DropHolder holder, int position) {
final DeadDrop deadDrop = deadDrops.get(position);
if (dropsPendingRemoval.contains(deadDrop)) {
holder.itemView.setBackgroundColor(Color.WHITE);
holder.undoIt.setVisibility(View.VISIBLE);
holder.rowWrapper.setVisibility(View.GONE);
} else {
holder.rowWrapper.setVisibility(View.VISIBLE);
holder.latitude.setText(Converts.latitudeToSexaString(deadDrop.getLatitude()));
holder.longitude.setText(Converts.longitudeToSexaString(deadDrop.getLongitude()));
holder.undoIt.setVisibility(View.GONE);
}
}
#Override
public int getItemCount() {
if (deadDrops != null)
return deadDrops.size();
else return 0;
}
void pendingRemoval(int position) {
final DeadDrop mDeadDrop = deadDrops.get(position);
if (!dropsPendingRemoval.contains(mDeadDrop)) {
dropsPendingRemoval.add(mDeadDrop);
notifyItemChanged(position);
Runnable pendingRemovalRunnable = new Runnable() {
#Override
public void run() {
// Here is the problem. After the first item is removed,
// the next drop to remove is not found in the newly updated
// list of items (deadDrops).
int pos = deadDrops.indexOf(mDeadDrop);
remove(pos);
}
};
mHandler.postDelayed(pendingRemovalRunnable, PENDING_REMOVAL_TIMEOUT);
pendingRunnables.put(mDeadDrop, pendingRemovalRunnable);
}
}
void setDeadDrops(List<DeadDrop> drops) {
deadDrops = drops;
notifyDataSetChanged();
}
private void remove(int position) {
DeadDrop drop = deadDrops.get(position);
dropsPendingRemoval.remove(drop);
if (deadDrops.contains(drop)) {
deadDrops.remove(position);
notifyItemRemoved(position);
((DeadDropActivity) context).mDeadDropViewModel.delete(drop);
notifyDataSetChanged();
}
}
boolean isPendingRemoval(int position) {
return dropsPendingRemoval.contains(deadDrops.get(position));
}
/**
* Drops List View Holder class
*/
protected class DropHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
LinearLayout rowWrapper;
TextView latitude, longitude;
ImageButton mapIt;
Button undoIt;
DropHolder(View itemView) {
super(itemView);
rowWrapper = itemView.findViewById(R.id.row_wrapper);
latitude = itemView.findViewById(R.id.latitude_sexagesimal);
longitude = itemView.findViewById(R.id.longitude_sexagesimal);
mapIt = itemView.findViewById(R.id.button_map_it);
undoIt = itemView.findViewById(R.id.undo_button);
mapIt.setOnClickListener(this);
undoIt.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.button_map_it) {
String gUri = String.format(Locale.ENGLISH,
"https://www.google.com/maps/#%f,%f," + DeadDropActivity.GMAPS_CLOSE_ZOOM + "z",
deadDrops.get(getLayoutPosition()).getLatitude(),
deadDrops.get(getLayoutPosition()).getLongitude());
Intent gIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(gUri));
gIntent.setClassName("com.google.android.apps.maps",
"com.google.android.maps.MapsActivity");
try {
context.startActivity(gIntent);
} catch (ActivityNotFoundException ex) {
try {
String uri = String.format(Locale.ENGLISH, "geo:%f,%f?z=25",
deadDrops.get(getLayoutPosition()).getLatitude(),
deadDrops.get(getLayoutPosition()).getLongitude());
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
context.startActivity(intent);
} catch (ActivityNotFoundException innerEx) {
Toast.makeText(context, "Please install a maps application or browser.",
Toast.LENGTH_LONG).show();
innerEx.printStackTrace();
}
}
Toast.makeText(context, "Map Button clicked at " + getLayoutPosition(), Toast.LENGTH_SHORT).show();
} else if (v.getId() == R.id.undo_button) {
DeadDrop deadDrop = deadDrops.get(getLayoutPosition());
// user wants to undo the removal, let's cancel the pending task
// Cancelling still works without issue.
Runnable pendingRemovalRunnable = pendingRunnables.get(deadDrop);
pendingRunnables.remove(deadDrop);
if (pendingRemovalRunnable != null)
mHandler.removeCallbacks(pendingRemovalRunnable);
dropsPendingRemoval.remove(deadDrop);
// this will rebind the row in "normal" state
notifyItemChanged(deadDrops.indexOf(deadDrop));
Log.d(TAG, TAG_CLASS + ".onClickUndo(" + getLayoutPosition() + ")");
}
}
}
/**
* Utility class
*/
public static class Converts {
static String latitudeToSexaString(double latitude) {
String latDir = (latitude < 0) ? "S" : "N";
double lat = Math.abs(latitude);
double s;
int d, m;
d = (int) lat;
m = (int) ((lat - d) * 60);
s = (((lat - d) * 60) - m) * 60;
return String.format(Locale.ENGLISH, "%02d\u00B0", d) +
String.format(Locale.ENGLISH, "%02d\u0027", m) +
String.format(Locale.ENGLISH, "%02.1f\"", s) + latDir;
}
static String longitudeToSexaString(double longitude) {
String lonDir = (longitude < 0) ? "W" : "E";
double lon = Math.abs(longitude);
double s;
int d, m;
d = (int) lon;
m = (int) ((lon - d) * 60);
s = (((lon - d) * 60) - m) * 60;
return String.format(Locale.ENGLISH, "%02d\u00B0", d) +
String.format(Locale.ENGLISH, "%02d\u0027", m) +
String.format(Locale.ENGLISH, "%02.1f\"", s) + lonDir;
}
}
}
Here is the logcat where it shows that the indexof is returning -1 because the instance is not found, but that is because it is a new instance of the same object (The ID is the same, but the object.toString() is different:
2019-07-14 02:29:17.890 18618-18618/com.daweber.deaddrop D/daweber.DD: .DropListAdapter.pendingRemoval(): 2
2019-07-14 02:29:17.890 18618-18618/com.daweber.deaddrop D/daweber.DD: .DropListAdapter.pendingRemoval(): {}
2019-07-14 02:29:17.890 18618-18618/com.daweber.deaddrop D/daweber.DD: .DropListAdapter.pendingRemoval(): ID|16
2019-07-14 02:29:20.896 18618-18618/com.daweber.deaddrop D/daweber.DD: .DropListAdapter.[Runnable]run(): 2
DropID = com.daweber.deaddrop.DeadDrop#d769128(ID|16)
DropsList = [com.daweber.deaddrop.DeadDrop#50eec1a, com.daweber.deaddrop.DeadDrop#966a34b, com.daweber.deaddrop.DeadDrop#d769128]
2019-07-14 02:29:20.992 18618-18618/com.daweber.deaddrop D/daweber.DD: .DeadDropActivity.[Observer].onChanged(): [com.daweber.deaddrop.DeadDrop#9f16479, com.daweber.deaddrop.DeadDrop#6fad5be]
2019-07-14 02:29:37.286 18618-18618/com.daweber.deaddrop D/daweber.DD: .DropListAdapter.pendingRemoval(): 1
2019-07-14 02:29:37.287 18618-18618/com.daweber.deaddrop D/daweber.DD: .DropListAdapter.pendingRemoval(): {com.daweber.deaddrop.DeadDrop#d769128=com.daweber.deaddrop.DropsListAdapter$1#38e0d6c}
2019-07-14 02:29:37.287 18618-18618/com.daweber.deaddrop D/daweber.DD: .DropListAdapter.pendingRemoval(): ID|15
2019-07-14 02:29:37.766 18618-18618/com.daweber.deaddrop D/daweber.DD: .DropListAdapter.pendingRemoval(): 0
2019-07-14 02:29:37.766 18618-18618/com.daweber.deaddrop D/daweber.DD: .DropListAdapter.pendingRemoval(): {com.daweber.deaddrop.DeadDrop#6fad5be=com.daweber.deaddrop.DropsListAdapter$1#4049458, com.daweber.deaddrop.DeadDrop#d769128=com.daweber.deaddrop.DropsListAdapter$1#38e0d6c}
2019-07-14 02:29:37.767 18618-18618/com.daweber.deaddrop D/daweber.DD: .DropListAdapter.pendingRemoval(): ID|4
2019-07-14 02:29:40.292 18618-18618/com.daweber.deaddrop D/daweber.DD: .DropListAdapter.[Runnable]run(): 1
DropID = com.daweber.deaddrop.DeadDrop#6fad5be(ID|15)
DropsList = [com.daweber.deaddrop.DeadDrop#9f16479, com.daweber.deaddrop.DeadDrop#6fad5be]
2019-07-14 02:29:40.358 18618-18618/com.daweber.deaddrop D/daweber.DD: .DeadDropActivity.[Observer].onChanged(): [com.daweber.deaddrop.DeadDrop#c9d4e22]
2019-07-14 02:29:40.769 18618-18618/com.daweber.deaddrop D/daweber.DD: .DropListAdapter.[Runnable]run(): -1
DropID = com.daweber.deaddrop.DeadDrop#9f16479(ID|4)
DropsList = [com.daweber.deaddrop.DeadDrop#c9d4e22]
2019-07-14 02:30:02.153 18766-18766/com.daweber.deaddrop D/daweber.DD: .DeadDropActivity.[Observer].onChanged(): [com.daweber.deaddrop.DeadDrop#ff36b61]
So, the question now becomes, how do I modify this line
int pos = deadDrops.indexOf(mDeadDrop);
to get the index of the object by looking up the object.getId() instead of the object signature?
So, I have found a "brute force" way to do this and it seems to prevent crashing, but if the list grew to 1000s of entries, this might not be the most efficient way, so if anyone has a better solution:
new run()
#Override
public void run() {
final String TAG_FUN = ".[Runnable]run(): ";
// TODO: Here is the problem.
for (int i = 0; i <= deadDrops.size(); i++) {
DeadDrop d = deadDrops.get(i);
if (d.getId() == mDeadDrop.getId()) {
int pos = deadDrops.indexOf(d);
Log.d(TAG, TAG_CLS + TAG_FUN + pos
+ "\nDropID = " + d.toString() + "(ID|" + d.getId() + ")"
+ "\nDropsList = " + deadDrops.toString());
remove(pos);
break;
}
}
}

android: how to make the method synchronized [duplicate]

This problem has bothered me for a long time. I use a cloud database called bmob, and I found that I can successfully get the data I want. However, there might be some mistakes in the loops, and I could only get the information of the last selected item.
p.s. I use an array list called Playlist to store the calculated data that I will use to display a list-view in the next activity.
here is my code:
public class DestinationActivity extends Activity implements OnClickListener, NumberPicker.OnValueChangeListener {
private TextView from_place, date, days, start_time, end_time, number, money_view;
private Button addButton, subButton;
private ImageView backButton, telephone;
private ListView listView;
private Button destinationOk_btn;
private ShapeLoadingDialog shapeLoadingDialog;
private Tip startTip;
private Calendar calendar;
private DatePickerDialog dialog;
private TimePickerDialog dialog2;
private List<Destination> destinationList = new ArrayList<Destination>();
private DestinationAdapter adapter;
private int number_value = 1;
private String time_start;
private String time_end;
private int travel_days;
double travelTime;//total playing time
double travel_time;
private int money;
private int num = 1;
private ArrayList<Integer> select_placeID = new ArrayList<Integer>();
public Map<Integer,Double> weightMap;
public List<Plan> planList = new ArrayList<Plan>();
int[] selectedID = new int[10];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.destination_layout);
//initialize the cloud database
Bmob.initialize(this, BmobConfig.APP_ID);
listView = (ListView) findViewById(R.id.list_destination);
destinationOk_btn = (Button) findViewById(R.id.okButton);
initDestinations(); // initialize the data
adapter = new DestinationAdapter(destinationList, DestinationActivity.this);
//adapter = new DestinationAdapter(this, destinationList, DestinationAdapter.getIsSelected());
listView.setAdapter(adapter);
//....listeners and textviews.......
//submit button
destinationOk_btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
select_placeID.clear();
for (int i = 0; i < destinationList.size(); i++) {
if (DestinationAdapter.getIsSelected().get(i)) {
select_placeID.add((i + 1));
}
}
//change to int array
selectedID = new int[select_placeID.size()];
for(int i = 0;i<select_placeID.size();i++){
selectedID[i] = select_placeID.get(i);
}
if (select_placeID.size() == 0) {
AlertDialog.Builder builder1 = new AlertDialog.Builder(DestinationActivity.this);
builder1.setMessage("no records");
builder1.show();
}
else {
AlertDialog.Builder builder = new AlertDialog.Builder(DestinationActivity.this);
builder.setMessage("waiting for magic...");
builder.show();
/**
* calculate the route
*/
if (validate()) {
new calRoute().execute();
}
}
}
});
}
//initialize the data
private void initDestinations() {
//........
}
#Override
public void onClick(View v) {
//.......
}
/**
* asynctask
*/
private class calRoute extends AsyncTask<Void, Void, List<Plan>>{
public calRoute(){
// TODO Auto-generated constructor stub
}
#Override
protected List<Plan> doInBackground(Void... params) {
List<Plan> result = calculate(time_start, time_end, travel_days);
return result;
}
#Override
protected void onPostExecute(List<Plan> result) {
super.onPostExecute(result);
if (result != null) {
Toast.makeText(DestinationActivity.this, "success", Toast.LENGTH_SHORT).show();
if(planList.size() > 0) {
Intent intent = new Intent();
intent.setClass(DestinationActivity.this, ActivityPlan.class);
intent.putParcelableArrayListExtra("planInfo", (ArrayList<? extends Parcelable>) planList);
startActivity(intent);
}
else{
Toast.makeText(DestinationActivity.this, "no plan", Toast.LENGTH_SHORT).show();
}
}
}
}
/**
*plan
**/
public List<Plan> calculate(String time_start, String time_end, int travel_days) {
SimpleDateFormat df = new SimpleDateFormat(("HH:mm"));
Date starttime = new Date();
Date endtime = new Date();
try {
starttime = df.parse(time_start);
} catch (ParseException e) {
e.printStackTrace();
}
try {
endtime = df.parse(time_end);
} catch (ParseException e) {
e.printStackTrace();
}
double l = endtime.getTime() - starttime.getTime();
double hour = (l / (60 * 60 * 1000));
double min = ((l / (60 * 1000)) - hour * 60);
if(min == 0){
min = 60;
}
else {
travel_time = ((1.0 * travel_days * hour) * (min / 60));
DecimalFormat decimalFormat = new DecimalFormat("#.0");
travelTime = Double.parseDouble(decimalFormat.format(travel_time));
}
weightMap = new LinkedHashMap<Integer, Double>(); //store weight
int totalPriority = 0;//total priority
final Destination start = new Destination(116.32133, 39.92269);
final HashMap<Integer, Integer> pMap = new HashMap<Integer, Integer>();
final HashMap<Integer, String> nameMap = new HashMap<Integer, String>();
final HashMap<Integer, Destination> objectMap = new LinkedHashMap<Integer, Destination>();
/**
* get the data from cloud database
*/
BmobQuery<Destination> query = new BmobQuery<Destination>();
for (int sid: selectedID) {
query.addWhereEqualTo("id", sid);
query.findObjects(new FindListener<Destination>() {
#Override
public void done(List<Destination> list, BmobException e) {
if (e == null) {
System.out.println("success:total" + list.size() + "items。");
for (Destination destination : list) {
int p = destination.getPriority();
int id = destination.getId();
String name = destination.getName();
double longitude = destination.getLongitude();
double latitude = destination.getLatitude();
objectMap.put(id, new Destination(longitude, latitude));
System.out.println(id);
double dis = DistanceUtil.distance(start.getLongitude(), start.getLatitude(),
longitude, latitude);
pMap.put(id, p);
weightMap.put(id, new Double(dis));
nameMap.put(id, name);
}
} else {
Log.i("bmob", "error:" + e.getMessage() + "," + e.getErrorCode());
}
}
});
}
for (Integer key : pMap.keySet()) {
int p = pMap.get(key).intValue();
totalPriority = totalPriority + p;
}
double weight = 0.0;
for (Map.Entry<Integer, Double> hm : weightMap.entrySet()) {
double hm2Value = pMap.get(hm.getKey());
weight = totalPriority / hm.getValue() * hm2Value;
weightMap.put(hm.getKey(), weight);
}
/**
* 按照weight值来排序
* 判断是否传递数据给plan_activity
*/
MapUtil.sortByValue(weightMap);
//排好序后计算距离
Iterator it = weightMap.entrySet().iterator();
int order = 0;
while (it.hasNext()) {
order++;
Map.Entry entry = (Map.Entry) it.next();
objectMap.put(new Integer(order), objectMap.get(entry.getKey()));
}
PlanTask planTask = new PlanTask();//封装了每个plan计算的方法
for (Map.Entry<Integer, Double> entry : weightMap.entrySet()) {
System.out.println("id= " + entry.getKey());
double play_time = planTask.calPlay_time(weightMap.size(),
weightMap.get(entry.getKey()), travelTime);
double driving_time = planTask.calDrive_time(DistanceUtil.distance(
objectMap.get(entry.getKey()).getLatitude(),
objectMap.get(entry.getKey()).getLongitude(),
objectMap.get(entry.getKey() + 1).getLatitude(),
objectMap.get(entry.getKey() + 1).getLongitude()
));
String arrive_time = "hello world";//未完待续
String place_name = nameMap.get(entry.getKey());
Plan plan = new Plan(place_name, arrive_time, driving_time, play_time);
//传递plan对象list
planList.add(entry.getKey(), plan);
}
return planList;
}
}
When I debug it, I found that in calculate() functions, the output of
BmobQuery<Destination> query = new BmobQuery<Destination>();
for (int sid: selectedID) {
query.addWhereEqualTo("id", sid);
query.findObjects(new FindListener<Destination>() {
#Override
public void done(List<Destination> list, BmobException e) {
if (e == null) {
System.out.println("success:total" + list.size() + "items。");
for (Destination destination : list) {
int p = destination.getPriority();
int id = destination.getId();
String name = destination.getName();
double longitude = destination.getLongitude();
double latitude = destination.getLatitude();
objectMap.put(id, new Destination(longitude, latitude));
System.out.println(id);
//calculate the distance
double dis = DistanceUtil.distance(start.getLongitude(), start.getLatitude(),
longitude, latitude);
pMap.put(id, p);
weightMap.put(id, new Double(dis));
nameMap.put(id, name);
}
} else {
Log.i("bmob", "error:" + e.getMessage() + "," + e.getErrorCode());
}
}
});
is "success:total 1 items." and after the loop, if I have selected 3 items, it would be "success:total 1 items." for 3 times and only the information of the last item is caught.
AND the size of three hash map: pMap, nameMap and objectMap are all zero. Why is it??? It is so strange...
There is no error in LogCAT, however, the ordered list view cannot display in the second activity. PLEASE help me, it has bothered me for a long time.
Thank you!!!
I couldn't figure out much unfortunately, since I am not really comfortable with reactive programming yet as the platform uses a lot of rxjava in general, but here is something that would enhance the code a little bit
final HashMap<Integer, Integer> pMap = new HashMap<Integer, Integer>();
final HashMap<Integer, String> nameMap = new HashMap<Integer, String>();
final HashMap<Integer, Destination> objectMap = new LinkedHashMap<Integer, Destination>();
/**
* get the data from cloud database
*/
BmobQuery<Destination> query = new BmobQuery<Destination>();
// this time only one list of three elements is added instead of three lists of one element each
query.addWhereContainedIn("id", Arrays.asList(selectedID));
query.findObjects(new FindListener<Destination>() {
#Override
public void done(List<Destination> list, BmobException e) {
if (e == null) {
System.out.println("success:total" + list.size() + "items。");
for (Destination destination : list) {
int p = destination.getPriority();
int id = destination.getId();
String name = destination.getName();
double longitude = destination.getLongitude();
double latitude = destination.getLatitude();
objectMap.put(id, new Destination(longitude, latitude));
System.out.println(id);
//calculate the distance
double dis = DistanceUtil.distance(start.getLongitude(), start.getLatitude(),
longitude, latitude);
pMap.put(id, p);
weightMap.put(id, new Double(dis));
nameMap.put(id, name);
}
// continue execution here though you won't be able to return a list of plans here
} else {
Log.i("bmob", "error:" + e.getMessage() + "," + e.getErrorCode());
}
}
});
Hope this helps :)
List<HashMap<Integer, Destination>> listmap=new ArrayList<>;
final HashMap<Integer, Destination> objectMap;
/**
* get the data from cloud database
*/
BmobQuery<Destination> query = new BmobQuery<Destination>();
// this time only one list of three elements is added instead of three lists of one element each
query.addWhereContainedIn("id", Arrays.asList(selectedID));
query.findObjects(new FindListener<Destination>() {
#Override
public void done(List<Destination> list, BmobException e) {
if (e == null) {
System.out.println("success:total" + list.size() + "items。");
for (Destination destination : list) {
objectMap = new LinkedHashMap<Integer, Destination>();
int id = destination.getId();
objectMap.put(id, destination);
listmap.add(objectMap);
}
// continue execution here though you won't be able to return a list of plans here
} else {
Log.i("bmob", "error:" + e.getMessage() + "," + e.getErrorCode());
}
}
Try this

How to sort a list of array from a-z?

I am trying to sort a list of array based on the name in alphabetical order which contain type, name, url and date. I retrieved the information from Browser.BookmarkColumns except for type.
Before:
Default Browser Google www.Google.com 14/12/2013
Default Browser BBC www.BBC.com 13/12/2015
Default Browser Amazon www.Amazon.com 11/11/2014
After:
Default Browser Amazon www.Amazon.com 11/11/2014
Default Browser BBC www.BBC.com 13/12/2015
Default Browser Google www.Google.com 14/12/2013
Here is what i have tried but it is not working.
int j = mCur.getCount();
String[] mType = new String[j];
String[] mTitles = new String[j];
String[] murls = new String[j];
long[] date = new long[j];
for (int q=0; q<(j-1); q++) {
String a = (mTitles[q]).toLowerCase();
String b = (mTitles[q+1].toLowerCase());
char[] c = a.toCharArray();
char[] d = b.toCharArray();
String temp, temp2, temp3 = null;
long temp4 = 0;
int lenc = c.length;
int lend = d.length;
int min =0;
int count =0;
if (lenc < lend)
min = lenc;
else
min = lend;
if (c[count] > d[count]) {
temp = mTitles[count];
temp2 = mType[count];
temp3 = murls[count];
temp4 = date[count];
mTitles[count] = mTitles[count + 1];
mType[count] = mType[count + 1];
murls[count] = murls[count + 1];
date[count] = date[count + 1];
mTitles[count + 1] = temp;
mType[count + 1] = temp2;
murls[count + 1] = temp3;
date[count + 1] = temp4;
} else if (c[count] == d[count]) {
for (int w = 1; w < min; w++) {
if (c[w] > d[w]) {
temp = mTitles[w];
temp2 = mType[w];
temp3 = murls[w];
temp4 = date[w];
mTitles[w] = mTitles[w + 1];
mType[w] = mType[w + 1];
murls[w] = murls[w + 1];
date[w] = date[w + 1];
mTitles[w + 1] = temp;
mType[w + 1] = temp2;
murls[w + 1] = temp3;
date[w + 1] = temp4;
}
}
}
}
Above answers are giving best example for efficient sorting Array list in java.
Before it please read description of above mentioned answer here
I just simplified above answer for your better understanding it gives exact output what u required.
ArrayList<UserContainer> userList = new ArrayList<>();
userList.add(new UserContainer("www.Google.com", "Google", "14/12/2013"));
userList.add(new UserContainer("www.BBC.com", "BBC", "13/12/2015"));
userList.add(new UserContainer("www.Amazon.com", "Amazon", "11/11/2014"));
Log.i("Before Sorting :", "==========================>>");
for (UserContainer obj : userList) {
System.out.println("Default Browser: \t" + obj.name + "\t" + obj.date + "\t" + obj.webSite);
}
Collections.sort(userList, new Comparator<UserContainer>() {
#Override
public int compare(UserContainer first, UserContainer second) {
return first.name.compareToIgnoreCase(second.name);
}
});
Log.i("After Sorting :", "==========================>>");
for (UserContainer obj : userList) {
System.out.println("Default Browser: \t" + obj.name + "\t" + obj.date + "\t" + obj.webSite);
}
Model Class:
public class UserContainer {
public UserContainer(String webSite, String name, String date) {
this.webSite = webSite;
this.name = name;
this.date = date;
}
public String webSite = "";
public String name = "";
public String date = "";
}
First of all it would be much simplier task if instead of sorting 3 string arrays + long array You encapsulate all the fields and create a class (lets call it MyData) containing all four fields. Then you can use put all newly create objects in some collection (for example ArrayList).
So, when you have your ArrayList<MyData> you can easliy use Collections.sort passing both your list and implementation of Comparator<T> interface where all the sorting logic would be.
For example, if you want to sort whole list using only String title field it can look like this:
Comparator<MyData> with implemented compare function compare(MyData o1, MyData o2){return o1.title.compareTo(o2);
My advice to create custom array list.
private ArrayList<UserContainer> userList=new ArrayList<UserContainer>();
UserContainer usercontainer=new UserContainer()
usercontainer.name=Amazon;
usercontainer.date=11/11/2014;
userList.add(usercontainer);
UserContainer usercontainer2=new UserContainer()
usercontainer.name=Google;
usercontainer.date=11/11/2014;
userList.add(usercontainer);
UserContainer usercontainer3=new UserContainer()
usercontainer.name=BBC;
usercontainer.date=11/11/2014;
userList.add(usercontainer);
Collections.sort(userList, new Comparator<UserContainer>() {
#Override
public int compare(UserContainer s1, UserContainer s2) {
return s1.name.compareToIgnoreCase(s2.name);
}
});
Model:-
public class UserContainer {
public String name = "";
public String date = "";
}
I hope to help you.
Create a class and use comparator or comparable.
for further reference please check (How to sort an ArrayList in Java)
Arrays.sort(stringArray);
Its a nice way to sort.
I recommend you to create a Object for example 'BrowserStoredData' for each element of the list. With the strings required:
public class BrowserStoredData implements Comparable<BrowserStoredData> {
String browserType;
String browserName;
String browserUrl;
String browserDate;
public BrowserStoredData(String browserType, String browserName,
String browserUrl, String browserDate) {
super();
this.browserType = browserType;
this.browserName = browserName;
this.browserUrl = browserUrl;
this.browserDate = browserDate;
}
public int compareTo(BrowserStoredData bsd) {
return (this.browserName).compareTo(bsd.browserName);
}
#Override
public String toString() {
return browserType + "\t\t" + browserName + "\t\t" + browserUrl
+ "\t\t" + browserDate;
}
}
With that object you easily can order a list of BrowserStoredData objects simply by using Collections.sort(yourList)
For example:
BrowserStoredData bsd1 = new BrowserStoredData("Default Browser", "Google", "www.Google.com", "14/12/2013");
BrowserStoredData bsd2 = new BrowserStoredData("Default Browser", "BBC", "www.BBC.com", "13/12/2015");
BrowserStoredData bsd3 = new BrowserStoredData("Default Browser", "Amazon", "www.Amazon.com", "11/11/2014");
List<BrowserStoredData> listBrowsers = new ArrayList<BrowserStoredData>();
listBrowsers.add(bsd1);
listBrowsers.add(bsd2);
listBrowsers.add(bsd3);
Collections.sort(listBrowsers);
for (int i = 0 ; i < listBrowsers.size() ; i++){
BrowserStoredData bsd = listBrowsers.get(i);
System.out.println(bsd.toString());
}
The exit will be:
Default Browser Amazon www.Amazon.com 11/11/2014
Default Browser BBC www.BBC.com 13/12/2015
Default Browser Google www.Google.com 14/12/201

Android: sort by date in the JSON data

I am new to Android. I'm trying to sort by the date in the JSON data, but nothing works. I'm not even getting an error. I've tried so many different ways, but its not working.
I did a lot of searching but could not figure out how to implement this. How can I sort this by the days column? Thank you in advance.
Here's my code
public class ParseJSONTask extends AsyncTask< Void , Void , Void > {
public Handler handler = new Handler();
public Activity act = null;
private static String TAG_SERVICES = "services";
private static String TAG_ID = "id";
private static String TAG_COMMAND = "command";
private static String TAG_DAYS = "days";
private static String TAG_HOURS = "hours";
private static String TAG_OSMS = "osms";
private static String TAG_ISMS = "isms";
private static String TAG_TIMEOUT = "timeout";
public String SMS_SENT = "SMS Gönderildi";
public String SMS_DELIVERED = "SMS İletildi";
public String serviceString = "";
ArrayList<ServiceData> services;
#Override
public void onPreExecute() {
super.onPreExecute();
services = new ArrayList<ServiceData>();
}
#Override
public Void doInBackground(Void... params) {
WebServiceHandler webServiceHandler = new WebServiceHandler();
String JsonStr = webServiceHandler.getJSONData("http://jsonblob.com/55e34310e4b01190df36e861");
try {
JSONObject jsonObject = new JSONObject(JsonStr);
final JSONArray contactsJSON = jsonObject.getJSONArray(TAG_SERVICES);
for (int i = 0; i < contactsJSON.length(); i++) {
ServiceData aServiceData = new ServiceData();
//json parse istedimiz veriyi kullanabiliriz.
JSONObject serviceObject = contactsJSON.getJSONObject(i);
aServiceData.id = serviceObject.getString(TAG_ID);
aServiceData.command = serviceObject.getString(TAG_COMMAND);
aServiceData.days = serviceObject.getString(TAG_DAYS);
aServiceData.hours = serviceObject.getString(TAG_HOURS);
aServiceData.osms = serviceObject.getString(TAG_OSMS);
aServiceData.isms = serviceObject.getString(TAG_ISMS);
aServiceData.timeout = serviceObject.getString(TAG_TIMEOUT);
String input = aServiceData.days + " " + aServiceData.hours;
Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(input);
long milliseconds = date.getTime();
final long millisecondsFromNow = milliseconds - (new Date()).getTime();
aServiceData.milliseconds = milliseconds;
services.add(aServiceData);
if(millisecondsFromNow > 0) {
new DateSendSMS().onCreate(aServiceData.days, aServiceData.hours, aServiceData.osms, aServiceData.command);
Thread.sleep(Integer.parseInt(aServiceData.timeout) * 60000);
}
//Timeout aşağı kısımda sürelendirilecek
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
String serviceString = "";
for (ServiceData aServiceData:services){
serviceString+=aServiceData.toString();
}
Collections.sort(services, new Comparator<ServiceData>() {
#Override
public int compare(ServiceData t1, ServiceData t2) {
return t1.milliseconds <= t2.milliseconds ? -1 : 1;
}
});
// here is sorted data
for (ServiceData aServiceData : services) {
// move DateSendSMS here. above you can add additional logic about millis
new DateSendSMS().onCreate(aServiceData.days, aServiceData.hours, aServiceData.osms, aServiceData.command);
Log.d("+++++", aServiceData.toString());
}
}
}
ServiceData Class:
public static class ServiceData {
public long milliseconds;
public String id = "";
public String command = "";
public String days = "";
public String hours = "";
public String osms = "";
public String isms = "";
public String timeout = "";
#Override
public String toString() {
return id + ", " + command + ", " + days + ", " + hours + ", " + osms + ", " + isms
+ ", " + timeout + "\n \n ";
}
}
Add time field to ServiceData class
ServiceDate {
...
long milliseconds;
...
}
Fill this field in for loop:
long milliseconds = date.getTime();
aServiceData.milliseconds = milliseconds;
Sort services in onPostExecute
Collections.sort(services, new Comparator<ServiceData>() {
#Override
public int compare(ServiceData t1, ServiceData t2) {
return t1.milliseconds <= t2.milliseconds ? -1 : 1;
}
});
I am not sure you can directly sort Json Data (I dont know weather there is a library that will actually do it - if so go for it). I Suggest you to put all the ServiceData into a collection (Which you do at the moment) and then Sort it.
You can write your own sorting algorithm or you can use a Java Collections library to do the sorting by implimention Comparable on your ServiceData class or using a Comparable and them you can use Colletions.sort() to sort your list.
Here is a good tutorial.

Error in Dijkstra algorithm in android

I am implementing the 'Dijkstra algorithm' in Android for making an app for Metro Network.
When I click on the button to show the path, it stops the app.
I have explicitly defined the graph to store in array adj[][].
MetroRoute class
public class MetroRoute extends Activity implements OnClickListener{
EditText source, destination;
TextView Route;
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.metroroute);
source = (EditText) findViewById(R.id.etSource);
destination = (EditText) findViewById(R.id.etDest);
button = (Button) findViewById(R.id.bGetroute);
Route = (TextView) findViewById(R.id.tvRoute);
button.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
int count, i;
count = findpath(Integer.parseInt(source.getText().toString()), Integer.parseInt(destination.getText().toString()), path, sdist );
if(sdist!=0)
{
Route.setText("Shortest distance is : \n" + sdist);
Route.setText("Shortest Path is : ");
for( i=count;i>1;i--)
Route.setText(path[i] + " -> ");
Route.setText(path[i]);
}
else
Route.setText("There is no path from source to destination node\n");
}
int adj[][] = {{3,2,3,0,5},{1,2,3,4,5},{1,2,3,4,5},{1,2,3,4,5},{1,2,3,4,5}};
int MAX = 10, TEMP = 0, PERM =1, INFINITY = 9999, path[], sdist=0, n=5 ;
private class Node {
int predecessor[];
int dist[]; /*minimum distance of node from source*/
int status[];
}
int findpath(int s,int d,int path[],int sdist)
{
Node state = new Node();
int i, min=0, count=0, current, newdist, u, v ;
sdist=0;
/* Make all nodes temporary */
for(i=1;i<=n;i++)
{
state.predecessor[i]=0;
state.dist[i] = INFINITY;
state.status[i] = TEMP;
}
/*Source node should be permanent*/
state.predecessor[s]=0;
state.dist[s] = 0;
state.status[s] = PERM;
/*Starting from source node until destination is found*/
current=s;
while(current!=d)
{
for(i=1;i<=n;i++)
{
/*Checks for adjacent temporary nodes */
if ( adj[current][i] > 0 && state.status[i] == TEMP )
{
newdist=state.dist[current] + adj[current][i];
/*Checks for Relabeling*/
if( newdist < state.dist[i] )
{
state.predecessor[i] = current;
state.dist[i] = newdist;
}
}
}
/*Search for temporary node with minimum distance make it current node*/
min=INFINITY;
current=0;
for(i=1;i<=n;i++)
{
if(state.status[i] == TEMP && state.dist[i] < min)
{
min = state.dist[i];
current=i;
}
}
if(current==0) /*If Source or Sink node is isolated*/
return 0;
state.status[current]=PERM;
}
/* Getting full path in array from destination to source */
while( current!=0 )
{
count++;
path[count]=current;
current=state.predecessor[current];
}
/*Getting distance from source to destination*/
for(i=count;i>1;i--)
{
u=path[i];
v=path[i-1];
sdist+= adj[u][v];
}
return (count) ;
}
}
The easiest way to find the problem is to use the console of the adk to see the exceptions thrown by the device. When you start your app from your IDE (Eclipse, Android Studio) in a virtual device, or even your smartphone, you will get logcat-messages, which will contain the exceptions like for example the NullPointerException. You will then find the lines where the exception is thrown and then you can do some further testing (like writing some values to the console (System.Out.println(...) or System.err.println(...)).
You can post your log so we can take a look at it.
You may want to use my Dijkstra-implementation, too:
public static ArrayList<Integer> dijkstra(Graph graph, Integer orig,
Integer dest, TreeMap<Integer, Integer> distance,
ArrayList<Integer> nodesLeft) throws Exception
{
Iterator<Integer> iterator = graph.getNodes().iterator();
Integer next;
TreeMap<Integer, ArrayList<Integer>> paths = new TreeMap<Integer, ArrayList<Integer>>();
while (iterator.hasNext()) {
next = iterator.next();
distance.put(next, -1);
paths.put(next, new ArrayList<Integer>());
}
distance.put(orig, 0);
nodesLeft.addAll(Collections.unmodifiableCollection(graph.getNodes()));
while (!nodesLeft.isEmpty()) {
int u = nodesLeft.get(0);
Collection<Integer> edgesOfU = graph.getEdges(u);
Iterator<Integer> itEdgesOfU = edgesOfU.iterator();
int nextEdge;
while (itEdgesOfU.hasNext()) {
nextEdge = itEdgesOfU.next();
if (nodesLeft.contains(nextEdge)) {
int distU = distance.get(u);
if ((distance.get(nextEdge) == -1)
|| (distU + 1) < distance.get(nextEdge)) {
distance.put(nextEdge, distU + 1);
ArrayList<Integer> tmpList = paths.get(nextEdge);
for (int a : paths.get(u)) {
tmpList.add(a);
}
tmpList.add(nextEdge);
}
}
}
nodesLeft.remove(0);
}
return paths.get(dest);
}
I used some self-defined Graphs with the following Interface:
import java.util.Collection;
public interface Graph {
public Integer addNode();
public void removeNode(Integer id) throws Exception,
UnsupportedOperationException;
public Collection<Integer> getNodes();
public boolean addEdge(Integer orig, Integer dest) throws Exception;
public boolean removeEdge(Integer orig, Integer dest) throws Exception,
UnsupportedOperationException;
public Collection<Integer> getEdges(Integer orig) throws Exception;
}

Categories

Resources