Below code is part of search box in my android app.
LoadCatalog is a async task for the api call, problem is whenever it is being called the editText stops taking new character for a fraction of second(skips a character in middle).
for ex- if the user want to enter "The book of leaves"...
it only sometimes take "The boo of " or "The bookof "
It skips the character, pls suggest what's wrong in my code.
private TextWatcher productEntered = new TextWatcher() {
long lastChange = 0;
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence enteredSequence, int start, int before, int count) {
searchbarActionClear.setVisibility(View.VISIBLE);
enteredText = enteredSequence;
if (CommonUtils.isConnectingToInternet(DashboardActivity.this)) {
if (enteredText.length() > 3) {
new Handler().postDelayed(new Runnable() {
public void run() {
if (System.currentTimeMillis() - lastChange >= 600) {
resetList();
toolbarSuggestionEditText.setTag(toolbarSuggestionEditText.getKeyListener());
toolbarSuggestionEditText.setKeyListener(null);
new LoadCatalog().execute(String.valueOf(enteredText));
}
}
}, 600);
lastChange = System.currentTimeMillis();
}
}
}
public void afterTextChanged(Editable s) {
}
};
private class LoadCatalog extends AsyncTask<String, Void, CustomResponse> {
#Override
protected CustomResponse doInBackground(String... params) {
String url;
if (categoryItem != null) {
url = String.format(AppConstants.URLs.SEARCH_WITH_CATEGORY, params[0], categoryItem);
} else {
url = String.format(AppConstants.URLs.SEARCH, params[0]);
}
CustomResponse response = HttpRequest.GET_REQUEST(url, DashboardActivity.this);
return response;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(CustomResponse result) {
try {
if (result.getResponseCode() == 200) {
JSONArray jsonArray = null;
jsonArray = new JSONArray(result.getResponseBody());
Suggestion suggestion = null;
if (jsonArray.length() > 0) {
suggestionList.clear();
suggestionList.add(new Suggestion(null, Suggestion.TYPE_SUGGESTION_HEADER));
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
suggestion = new Suggestion(jsonObject.getString("name"),
jsonObject.getString("category"),
Suggestion.TYPE_SUGGESTION);
suggestionList.add(suggestion);
suggestionAdapter.notifyDataSetChanged();
}
toolbarSuggestionEditText.setKeyListener((KeyListener) toolbarSuggestionEditText.getTag());
} else {
toolbarSuggestionEditText.setKeyListener((KeyListener) toolbarSuggestionEditText.getTag());
Toast.makeText(DashboardActivity.this, "No item match with your search", Toast.LENGTH_SHORT).show();
suggestionList.clear();
}
} else {
toolbarSuggestionEditText.setKeyListener((KeyListener) toolbarSuggestionEditText.getTag());
}
} catch (JSONException e) {
toolbarSuggestionEditText.setKeyListener((KeyListener) toolbarSuggestionEditText.getTag());
e.printStackTrace();
}
}
}
Related
Following code is used for getting the new data from json on scroll of list view . But after getting the new json it does not add the new one from json instead it takes the same data that are in the first json .
Please Help me with this issue .
My Activity .
public class ProductView extends AppCompatActivity {
ListView list_product;
String json;
ProgressActivity loadingview;
int current_page = 1;
int totalPage = 1;
int Pagecount = 1;
Toolbar toolbar;
GetProductAdapter productAdapter;
List<BeanGetProducts> beanGetProductses = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_view);
toolbar = (Toolbar) findViewById(R.id.back_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onBackPressed();
}
});
ImageView img_home = (ImageView) findViewById(R.id.dr_image_home);
img_home.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(ProductView.this, AdminAccess.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
});
list_product = (ListView) findViewById(R.id.list_products);
productAdapter = new GetProductAdapter(beanGetProductses, ProductView.this, getApplicationContext());
list_product.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView absListView, int i) {
}
#Override
public void onScroll(AbsListView absListView, int firstItem, int visibleItemCount, int totalItem) {
int total = firstItem + visibleItemCount;
if (Pagecount < totalPage) {
if (total == totalItem) {
Pagecount++;
new getProducts(Pagecount).execute();
productAdapter.notifyDataSetChanged();
list_product.setAdapter(productAdapter);
}
}
}
});
new getProducts(current_page).execute();
}
public class getProducts extends AsyncTask<Void, Void, String> {
int pageNo;
public getProducts(int pageNo) {
this.pageNo = pageNo;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
try {
loadingview = new ProgressActivity(ProductView.this, "");
loadingview.setCancelable(false);
loadingview.show();
} catch (Exception e) {
}
}
#Override
protected String doInBackground(Void... voids) {
List<NameValuePair> pairs = new ArrayList<>();
pairs.add(new BasicNameValuePair("", String.valueOf(pageNo)));
json = new ServiceHandler().makeServiceCall(GlobalLinks.mainLink + GlobalLinks.productDetails, ServiceHandler.POST, pairs);
Log.e("Parameters", "" + pairs);
return json;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
loadingview.dismiss();
System.out.println(s);
try {
if (!Internet.isConnectingToInternet(getApplicationContext())) {
Internet.noInternet(getApplicationContext());
} else {
if (s.equalsIgnoreCase(null) || s.equalsIgnoreCase("") || s.equalsIgnoreCase("null") || s.length() == 0) {
GlobalUse.nullJSON(getApplicationContext());
} else {
JSONObject mainObject = new JSONObject(s);
boolean status = mainObject.getBoolean("status");
String message = mainObject.getString("message");
totalPage = mainObject.getInt("total_page");
Log.e("total_page", "" + totalPage);
Toast.makeText(getApplicationContext(), "" + message, Toast.LENGTH_LONG).show();
if (status == true) {
JSONArray dataArray = mainObject.getJSONArray("data");
for (int i = 0; i < dataArray.length(); i++) {
JSONObject object = dataArray.getJSONObject(i);
JSONObject getProductObject = object.getJSONObject("GetProduct");
BeanGetProducts getProducts = new BeanGetProducts();
getProducts.setProduct_id(getProductObject.getString("product_id"));
getProducts.setImage(getProductObject.getString("image"));
getProducts.setSku(getProductObject.getString("sku"));
getProducts.setQuantity(getProductObject.getString("quantity"));
getProducts.setPrice(getProductObject.getString("price"));
getProducts.setStock_status_id(getProductObject.getString("stock_status_id"));
JSONObject product_description = object.getJSONObject("Product_Description");
getProducts.setName(product_description.getString("name"));
getProducts.setDescription(product_description.getString("description"));
JSONObject SpecialPrice = object.getJSONObject("SpecialPrice");
getProducts.setSpecialPrice(SpecialPrice.getString("price"));
beanGetProductses.add(getProducts);
}
// productAdapter = new GetProductAdapter(beanGetProductses, ProductView.this, getApplicationContext());
productAdapter.notifyDataSetChanged();
list_product.setAdapter(productAdapter);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public void onBackPressed() {
Intent intent = new Intent(getApplicationContext(), AdminAccess.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}
}
Crate a new class named as EndlessScrollListener
import android.widget.AbsListView;
public abstract class EndlessScrollListener implements AbsListView.OnScrollListener {
// The minimum number of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
public EndlessScrollListener() {
}
public EndlessScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
public EndlessScrollListener(int visibleThreshold, int startPage) {
this.visibleThreshold = visibleThreshold;
this.startingPageIndex = startPage;
this.currentPage = startPage;
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) { this.loading = true; }
}
// If it's still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
currentPage++;
}
// If it isn't currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
if (!loading && (firstVisibleItem + visibleItemCount + visibleThreshold) >= totalItemCount ) {
loading = onLoadMore(currentPage + 1, totalItemCount);
}
}
// Defines the process for actually loading more data based on page
// Returns true if more data is being loaded; returns false if there is no more data to load.
public abstract boolean onLoadMore(int page, int totalItemsCount);
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// Don't take any action on changed
}
}
Then change your code as below.
The pagecount which you are passing in you asynctask is actually the size of a list. So you can update this variable this after laoding data from the network.
public class ProductView extends AppCompatActivity {
ListView list_product;
String json;
ProgressActivity loadingview;
int Pagecount = 0
Toolbar toolbar;
GetProductAdapter productAdapter;
List<BeanGetProducts> beanGetProductses = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_view);
toolbar = (Toolbar) findViewById(R.id.back_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onBackPressed();
}
});
ImageView img_home = (ImageView) findViewById(R.id.dr_image_home);
img_home.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(ProductView.this, AdminAccess.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
});
list_product = (ListView) findViewById(R.id.list_products);
productAdapter = new GetProductAdapter(beanGetProductses, ProductView.this, getApplicationContext());
// Load first time data and insert into list.
new getProducts(Pagecount).execute();
list_product.setOnScrollListener(new EndlessScrollListener() {
#Override
public boolean onLoadMore(int page, int totalItemsCount) {
// Triggered only when new data needs to be appended to the list
// Add whatever code is needed to append new items to your AdapterView
new getProducts(Pagecount).execute();
// or loadNextDataFromApi(totalItemsCount);
return true; // ONLY if more data is actually being loaded; false otherwise.
}
});
}
public class getProducts extends AsyncTask<Void, Void, String> {
int pageNo;
public getProducts(int pageNo) {
this.pageNo = pageNo;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
try {
loadingv
iew = new ProgressActivity(ProductView.this, "");
loadingview.setCancelable(false);
loadingview.show();
} catch (Exception e) {
}
}
#Override
protected String doInBackground(Void... voids) {
List<NameValuePair> pairs = new ArrayList<>();
pairs.add(new BasicNameValuePair("", String.valueOf(pageNo)));
json = new ServiceHandler().makeServiceCall(GlobalLinks.mainLink + GlobalLinks.productDetails, ServiceHandler.POST, pairs);
Log.e("Parameters", "" + pairs);
return json;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
loadingview.dismiss();
System.out.println(s);
try {
if (!Internet.isConnectingToInternet(getApplicationContext())) {
Internet.noInternet(getApplicationContext());
} else {
if (s.equalsIgnoreCase(null) || s.equalsIgnoreCase("") || s.equalsIgnoreCase("null") || s.length() == 0) {
GlobalUse.nullJSON(getApplicationContext());
} else {
JSONObject mainObject = new JSONObject(s);
boolean status = mainObject.getBoolean("status");
String message = mainObject.getString("message");
totalPage = mainObject.getInt("total_page");
Log.e("total_page", "" + totalPage);
Toast.makeText(getApplicationContext(), "" + message, Toast.LENGTH_LONG).show();
if (status == true) {
JSONArray dataArray = mainObject.getJSONArray("data");
// Update Pagecount here
Pagecount = Pagecount + dataArray.length();
for (int i = 0; i < dataArray.length(); i++) {
JSONObject object = dataArray.getJSONObject(i);
JSONObject getProductObject = object.getJSONObject("GetProduct");
BeanGetProducts getProducts = new BeanGetProducts();
getProducts.setProduct_id(getProductObject.getString("product_id"));
getProducts.setImage(getProductObject.getString("image"));
getProducts.setSku(getProductObject.getString("sku"));
getProducts.setQuantity(getProductObject.getString("quantity"));
getProducts.setPrice(getProductObject.getString("price"));
getProducts.setStock_status_id(getProductObject.getString("stock_status_id"));
JSONObject product_description = object.getJSONObject("Product_Description");
getProducts.setName(product_description.getString("name"));
getProducts.setDescription(product_description.getString("description"));
JSONObject SpecialPrice = object.getJSONObject("SpecialPrice");
getProducts.setSpecialPrice(SpecialPrice.getString("price"));
beanGetProductses.add(getProducts);
productAdapter.notifyDataSetChanged();
}
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public void onBackPressed() {
Intent intent = new Intent(getApplicationContext(), AdminAccess.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}
}
Hi I have one issue in my AutoCompleteTextView with AsynTask web service.
If i type the word in AutoCompleteTextView very fast in Textwatcher, each time it goes to web service to fetch the data and displayed in Dropdown.
But if i type very fast,the dropdown shows previous data and again shows the current data in AutocompleteTextview and data is interrupted.How to avoid this issue in Android?
autoCompleteTextView1.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
itemClicked = false;
if (!beforeTextChanged.equals(s.toString()) && !selectedText) { //Here we check selectedText
System.out.println("itemClicked" + itemClicked);
sText = s.toString();
if (sText.length() > 2) {
try {
autoCompleteTextView1.dismissDropDown();
autoCompleteTextView1.setAdapter(null);
Async1 = new NewAsync1(getActivity(),sText);
Async1 .execute();
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
loadprogress_bar.setVisibility(View.INVISIBLE);
arrayList.clear();
adapter.clear();
adapter = new AutoCompleteAdapter(getActivity(), R.layout.customer_auto, R.id.customerNameLabel, arrayList);
autoCompleteTextView1.setAdapter(null);
autoCompleteTextView1.dismissDropDown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
selectedText = false; //Clear selectedText flag
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
itemClicked = false;
beforeTextChanged = s.toString();
}
#Override
public void afterTextChanged(Editable s) {
itemClicked = false;
}
});
// NewOrderAsync Webservice
public class NewAsync1 extends AsyncTask<String, String, String> {
Activity mActivity;
JSONObject jObject;
String value;
ProgressDialog progressDialog;
public NewAsync1 (Activity mActivity,String value)
{
this.mActivity=mActivity;
this.value= value;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method
super.onPreExecute();
loadprogress_bar.setVisibility(View.VISIBLE);
}
#Override
protected String doInBackground(String... params) {
try {
String restUrl = "";
System.out.println("searchurl"+Url);
response = client.getJSONfromURL(restUrl);
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
#Override
protected void onPostExecute(String response) {
// TODO Auto-generated method stub
super.onPostExecute(response);
loadprogress_bar.setVisibility(View.INVISIBLE);
try{
JSONObject obj=new JSONObject(response);
JSONArray arr=obj.getJSONArray("ItemResult");
arraylist=ApiCalls.getArraylistfromJson(arr.toString());
arrayList = new ArrayList<String>();
for (int i = 0; i < arr.length(); i++) {
JSONObject obj1=arr.getJSONObject(i);
arrayList.add(obj1.getString("Name"));
}
//Create adapter
adapter = new AutoCompleteAdapter(getActivity(), R.layout.customer_auto, R.id.customerNameLabel, arrayList);
autoCompleteTextView1.setThreshold(1);
autoCompleteTextView1.setAdapter(adapter);
}catch (JSONException e){
e.printStackTrace();
}
if (!autoCompleteTextView1.isPopupShowing()) {
autoCompleteTextView1.showDropDown();
}
}
}
In my android application, there is a app file at the sd card, and the same in our server, but the data in the server may be updated.
So I make an activity to check if latest data is avaiable.
This is an example, there is only one button "Check", when user hit this button, I will get the information of the local data, and then reqest to the server to check if it can be udpated.(THis is done by the CheckTask and a progress dialog will show up during the checking).
Then if a update is requred, I will provide a Dialog to tell the user, they can choose "Download Now" or "Download Later", if they choose "Download Now", a DownLoadTask will be executed,and a new ProgressDialog will be created to show the progress of the download.
Now I meet a problem:
Everything works well unless user click the "Download Now" and then cancel the download.
Then when user click the "Check" button, the CheckTask will not work normally.
This is the codes:
public class MyActivity extends Activity {
private DecimalFormat format = new DecimalFormat("0.#");
private final int Dialog_Offline_Check_HaveUpdate = 13;
private final int Dialog_Offline_Download = 14;
private CheckTask mCheckTask;
private ProgressDialog mCheckProgressDialog;
private DownloadTask mDownloadTask;
private ProgressDialog mDownloadProgressDialog;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.setupView();
}
private void setupView() {
mCheckProgressDialog = new ProgressDialog(this);
mCheckProgressDialog.setCanceledOnTouchOutside(false);
findViewById(R.id.check).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startCheckTask();
}
});
}
private void startCheckTask() {
if (mDownloadTask != null && !mDownloadTask.isCancelled()) {
showDialog(Dialog_Offline_Download);
} else {
//for debug
String data = String.format("{\"name\":\"%s\",\"size\":123455,\"lastModifiedTime\":\"2014-1-1\",\"hasUpdate\":false}", "Old Data");
AppData appData = null;
try {
appData = buildMapData(data);
} catch (JSONException e) {
e.printStackTrace();
}
if (mCheckTask != null) mCheckTask.cancel(true);
mCheckTask = new CheckTask();
mCheckTask.execute(String.format("http://xxxx?t=%s", appData.lastModifiedTime));
}
}
private void startDownLoadTask() {
if (mDownloadTask != null) {
mDownloadTask.cancel(true);
}
mDownloadTask = new DownloadTask();
mDownloadTask.execute("https://dl.google.com/android/adt/adt-bundle-windows-x86-20131030.zip"); //for debug
showDialog(Dialog_Offline_Download);
}
#Override
protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
switch (id) {
case Dialog_Offline_Check_HaveUpdate:
builder.setTitle("Check Update").setPositiveButton("Download Now", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
startDownLoadTask();
}
}).setNegativeButton("Download Later", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
}).setMessage("Latest Data avaiable!");
return builder.create();
case Dialog_Offline_Download:
mDownloadProgressDialog = new ProgressDialog(this);
mDownloadProgressDialog.setTitle("Download Latest Data");
mDownloadProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDownloadProgressDialog.setMax(100);
mDownloadProgressDialog.setButton(DialogInterface.BUTTON_POSITIVE, "Do it in Background", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
}
});
mDownloadProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
if (mDownloadTask != null)
mDownloadTask.cancel(true);
}
});
mDownloadProgressDialog.setMessage("");
return mDownloadProgressDialog;
}
return null;
}
#Override
protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
switch (id) {
case Dialog_Offline_Check_HaveUpdate:
String msgg;
AppData appData1 = (AppData) args.getSerializable("data");
if (appData1 != null) {
msgg = String.format("%s\n%s: %s \n%s: %s\n%s: %s", "New Data Avaiable",
"Name", appData1.name,
"Size", makeFileSizeReadable(appData1.size),
"Last Update Time", appData1.lastModifiedTime);
} else {
msgg = "";
}
((AlertDialog) dialog).setMessage(msgg);
break;
}
}
private String makeFileSizeReadable(long size) {
double value;
String unit;
if (size < 1024) {
// < 1k
value = size;
unit = "Byte";
} else if (size < 1024 * 1024) {
// 1k,1M
value = size / 1024d;
unit = "Kb";
} else {
value = size / 1024d / 1024d;
unit = "Mb";
}
return String.format("%s %s", format.format(value), unit);
}
class CheckTask extends AsyncTask<String, Void, AppData> {
private String errorMsg;
private boolean cancel = false;
#Override
protected AppData doInBackground(String... urls) {
String url = urls[0];
//for debug
String response = String.format("{\"name\":\"%s\",\"size\":222222,\"lastModifiedTime\":\"2014-1-5\",\"hasUpdate\":true}", "New Data");
Log.d("map.setting", String.format("start parse result: [%s]", response));
AppData md = null;
try {
md = buildMapData(response);
} catch (JSONException e) {
e.printStackTrace();
Log.e("map.setting", "error when parse:" + e.getMessage());
}
Log.d("map.setting", "get md:" + md);
return md;
}
#Override
protected void onPreExecute() {
mCheckProgressDialog.setMessage("Checking...");
mCheckProgressDialog.show();
}
#Override
protected void onPostExecute(AppData appData) {
mCheckProgressDialog.dismiss();
if (appData == null) {
return;
}
if (appData.hasUpdate) {
Bundle bd = new Bundle();
bd.putSerializable("data", appData);
showDialog(Dialog_Offline_Check_HaveUpdate, bd);
} else {
Toast.makeText(MyActivity.this, "Your data is the latest!", Toast.LENGTH_SHORT).show();
}
}
}
private AppData buildMapData(String response) throws JSONException {
JSONObject root = new JSONObject(response);
String name = root.getString("name");
long size = root.getLong("size");
String lastModifiedTime = root.getString("lastModifiedTime");
boolean hasUpdate = root.getBoolean("hasUpdate");
AppData md = new AppData();
md.name = name;
md.lastModifiedTime = lastModifiedTime;
md.size = size;
md.hasUpdate = hasUpdate;
return md;
}
class DownloadTask extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... sUrl) {
try {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return null;
}
int fileLength = connection.getContentLength();
// download the file
input = connection.getInputStream();
output = new FileOutputStream(Environment.getExternalStorageDirectory() + "/tmp.data", false);
byte data[] = new byte[4096];
int total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
if (fileLength > 0)
publishProgress(total * 100 / fileLength, total, fileLength);
output.write(data, 0, count);
}
} catch (Exception e) {
return null;
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
} finally {
// wl.release();
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
//progress current total
if (mDownloadProgressDialog != null) {
mDownloadProgressDialog.setProgress(values[0]);
String msg = String.format("Progress:%s/%s", makeFileSizeReadable(values[1]), makeFileSizeReadable(values[2]));
mDownloadProgressDialog.setMessage(msg);
}
}
#Override
protected void onPostExecute(String res) {
//map file downloaded replace the old file
}
#Override
protected void onCancelled() {
super.onCancelled();
}
}
}
class AppData implements Serializable {
public String name;
public String lastModifiedTime;
public long size;
public boolean hasUpdate;
}
Anyone can find what is the problem?
Is that you encounter AsynTask's bug after HONEYCOMB?
Order of execution
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.
In our project we use AsynTask like this:
public void executeParallelly(Params... params) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
task.execute(params);
} else {
task.executeOnExecutor(AsynTask.THREAD_POOL_EXECUTOR, params);
}
}
I have the next code to make search of artist and songs on the spotify servers. I have an autocomplete text but my problem is if I search for something, like "David Guetta" and I try to delete with backspace ( <-- ) everytime that I delete one character it makes a search, and if I do it so fast the app crashes (heavy usage?). I don't know really if it is for that question.
What can I do to fix this? With a wait time to search it can be fixed but I don't know how to do it.
Can you help me with this? Thank you.
This is my SearchMusic.java code.
public class SearchMusic extends Activity {
AutoCompleteTextView autoCompleteSongs;
String searchTerms;
String[] arrayArtist = new String[64];
String[] arrayTrack = new String[64];
ArrayAdapter<String> adapter;
List<String> songs;
List<String> lArtist;
List<String> lTrack;
boolean bothsearchs = false; // Controlamos que haya busqueda por artista y
// pista si uno no existe.
int nArtist = 0; // iterator
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_music);
autoCompleteSongs = (AutoCompleteTextView) findViewById(R.id.autoCompletePetition);
final ArrayAdapter<String> list = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line);
// autoCompleteSongs.setThreshold(1);
// autoCompleteSongs.addTextChangedListener(this);
// autoCompleteSongs.setAdapter(new
// ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,
// item));
autoCompleteSongs.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if (s.length() > 3) {
searchTerms = s.toString();
searchTerms = searchTerms.replace(" ", "+");
// Buscamos por artista
AsyncHttpClient client = new AsyncHttpClient();
client.get("http://ws.spotify.com/search/1/artist.json?q="
+ searchTerms + "*", null,
new JsonHttpResponseHandler() {
public void onSuccess(JSONObject data) {
try {
// Hay artistas con ese nombre
if (data.length() > 0) {
JSONArray artist = new JSONArray(
data.getJSONArray("artists")
.toString());
for (int i = 0; i < 6; i++) {
JSONObject orden = artist
.getJSONObject(i);
String name = orden
.getString("name");
list.add(name);
arrayArtist[i] = name;
arrayTrack[i] = "";
nArtist++;
}
} else {
bothsearchs = true;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable arg0) {
}
});
// Buscamos por pista
client.get("http://ws.spotify.com/search/1/track.json?q="
+ searchTerms + "*", null,
new JsonHttpResponseHandler() {
public void onSuccess(JSONObject spoty) {
try {
JSONArray artist = new JSONArray(spoty
.getJSONArray("tracks")
.toString());
for (int i = nArtist; i < nArtist + 6 ; i++) {
JSONObject orden = artist
.getJSONObject(i);
String name = orden
.getString("name");
JSONArray nameArtist = new JSONArray(
orden.getJSONArray(
"artists")
.toString());
JSONObject namArt = nameArtist
.getJSONObject(0);
String nameArt = namArt
.getString("name");
list.add("[" + nameArt + "] "
+ name);
arrayArtist[i] = nameArt;
arrayTrack[i] = name;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable arg0) {
}
});
list.notifyDataSetChanged();
TextView text = (TextView) findViewById(R.id.petitionTextView);
for(int i = 0; i < 12; i++){
Log.i("AART", "" + arrayArtist[i]);
Log.i("ATRA", "" + arrayTrack[i]);
}
if(arrayArtist[0] == null && arrayTrack[0] == ""){
text.setText("No hay resultados");
}else{
for(int i = 0; i < 12; i++){
String register = "<font color=#64c7eb>" + arrayArtist[i] + "</font> <font color=#272527>" + arrayTrack[i] + "</font></br>";
text.setText(Html.fromHtml(register));
}
}
}
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void afterTextChanged(Editable s) {
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.search_music, menu);
return true;
}
}
If I am right, this the code that I need. The problem is how to stop it. ¬¬
//Declare the timer
Timer t = new Timer();
//Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//Called each time when 1000 milliseconds (1 second) (the period parameter)
}
},
//Set how long before to start calling the TimerTask (in milliseconds)
0,
//Set the amount of time between each execution (in milliseconds)
1000);
I think you are already giving a good solution.
Try wrapping the http request within a TimerTask and create a timer mechanism to cancel out the TimerTask.
Example (not tested):
public class SearchMusic extends Activity {
AutoCompleteTextView autoCompleteSongs;
String searchTerms;
String[] arrayArtist = new String[64];
String[] arrayTrack = new String[64];
ArrayAdapter<String> adapter;
List<String> songs;
List<String> lArtist;
List<String> lTrack;
//Declare and initialize the timer
Timer t = new Timer();
boolean bothsearchs = false; // Controlamos que haya busqueda por artista y
// pista si uno no existe.
int nArtist = 0; // iterator
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_music);
autoCompleteSongs = (AutoCompleteTextView) findViewById(R.id.autoCompletePetition);
final ArrayAdapter<String> list = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line);
// autoCompleteSongs.setThreshold(1);
// autoCompleteSongs.addTextChangedListener(this);
// autoCompleteSongs.setAdapter(new
// ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,
// item));
autoCompleteSongs.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if (s.length() > 3) {
// Cancel the Timer and all scheduled tasks
t.cancel();
t.purge();
t = new Timer();
//Set the schedule function and rate
t.schedule(new TimerTask() {
#Override
public void run()
{
//Called each time when 1000 milliseconds (1 second) (the period parameter)
searchTerms = s.toString();
searchTerms = searchTerms.replace(" ", "+");
// Buscamos por artista
AsyncHttpClient client = new AsyncHttpClient();
client.get("http://ws.spotify.com/search/1/artist.json?q="
+ searchTerms + "*", null,
new JsonHttpResponseHandler() {
public void onSuccess(JSONObject data) {
try {
// Hay artistas con ese nombre
if (data.length() > 0) {
JSONArray artist = new JSONArray(
data.getJSONArray("artists")
.toString());
for (int i = 0; i < 6; i++) {
JSONObject orden = artist
.getJSONObject(i);
String name = orden
.getString("name");
list.add(name);
arrayArtist[i] = name;
arrayTrack[i] = "";
nArtist++;
}
} else {
bothsearchs = true;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable arg0) {
}
});
// Buscamos por pista
client.get("http://ws.spotify.com/search/1/track.json?q="
+ searchTerms + "*", null,
new JsonHttpResponseHandler() {
public void onSuccess(JSONObject spoty) {
try {
JSONArray artist = new JSONArray(spoty
.getJSONArray("tracks")
.toString());
for (int i = nArtist; i < nArtist + 6 ; i++) {
JSONObject orden = artist
.getJSONObject(i);
String name = orden
.getString("name");
JSONArray nameArtist = new JSONArray(
orden.getJSONArray(
"artists")
.toString());
JSONObject namArt = nameArtist
.getJSONObject(0);
String nameArt = namArt
.getString("name");
list.add("[" + nameArt + "] "
+ name);
arrayArtist[i] = nameArt;
arrayTrack[i] = name;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable arg0) {
}
});
list.notifyDataSetChanged();
TextView text = (TextView) findViewById(R.id.petitionTextView);
for(int i = 0; i < 12; i++){
Log.i("AART", "" + arrayArtist[i]);
Log.i("ATRA", "" + arrayTrack[i]);
}
if(arrayArtist[0] == null && arrayTrack[0] == ""){
text.setText("No hay resultados");
}else{
for(int i = 0; i < 12; i++){
String register = "<font color=#64c7eb>" + arrayArtist[i] + "</font> <font color=#272527>" + arrayTrack[i] + "</font></br>";
text.setText(Html.fromHtml(register));
}
}
}
},
//Set how long before to start calling the TimerTask (in milliseconds)
0,
//Set the amount of time between each execution (in milliseconds)
1000);
}
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void afterTextChanged(Editable s) {
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.search_music, menu);
return true;
}
}
The best thing you can do is using a handler, this is a simple example with a button. But the button represents the backspace on your code.
The idea is to schedule the search action within 500 miliseconds but when someone hits the search button again, we reschedule the search action until the user stops hitting the search button.
Good luck!
public class MyActivity extends Activity implements OnClickListener
{
protected static final int MSG_SEARCH = 0;
protected Button buttonSearch;
protected Handler handler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
switch (msg.what)
{
case MSG_SEARCH:
MyActivity.this.search();
break;
}
}
};
#Override
public void onClick(View inView)
{
if (inView == this.buttonSearch)
{
this.handler.removeMessages(MSG_SEARCH);
final Message message = Message.obtain(this.handler, MSG_SEARCH);
this.handler.sendMessageDelayed(message, 500);
}
}
protected void search()
{
// your seach code
}
}
I had the same problem when i was using GooglePlaceApi to get list of addresses. I used synchronized in the performFiltering(), publishResults() and also the method that does the rest call. It worked for me. Maybe you can give a try.
synchronized (input)
{
// Do something inside
}
My code is following ...
public class NameListActivity extends Activity implements TextWatcher {
private Button add = null;
private AutoCompleteTextView editAuto = null;
private Button chfrlist = null;
private ImageView im = null;
String access_token = new String();
private ImageView infobtn = null;
private PopupWindow popupWindow;
private View view;
private ProgressDialog pd;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_name_list);
access_token = MainService.readToken();
add = (Button) findViewById(R.id.add_button);
editAuto = (AutoCompleteTextView) findViewById(R.id.editAuto);
chfrlist = (Button) findViewById(R.id.chfrlistbutton);
im = (ImageView) findViewById(R.id.helpact);
im.setOnClickListener(new ImageListener());
infobtn = (ImageView) findViewById(R.id.informbtn);
initPopupWindow();
infobtn.setOnClickListener(new infobtnListener());
editAuto.addTextChangedListener(this);
add.setOnClickListener(new addListener());
chfrlist.setOnClickListener(new ChfrListListener());
}
public class addListener implements OnClickListener {
public void onClick(View v) {
addTask task = new addTask();
task.execute();
editAuto.setText("");
}
}
public void afterTextChanged(Editable arg0) {
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
onTextChangedTask task = new onTextChangedTask();
task.execute();
}
public class onTextChangedTask extends AsyncTask<Void, Void, Void> {
ArrayAdapter<String> adapter = null;
String[] userName = null;
String q = null;
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject = null;
ArrayList<String> userNameArrayList = new ArrayList<String>();
Weibo weibo = new Weibo();
#Override
protected void onPreExecute() {
weibo.setToken(access_token);
q = editAuto.getText().toString();
System.out.println("start onTextChanged");
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
if (q.length() != 0) {
System.out.println("q is " + q);
String s1 = "https://api.weibo.com/search/suggestions/users.json";
try {
jsonArray = Weibo.client.get(s1,
new PostParameter[] { new PostParameter("q", q) })
.asJSONArray();
} catch (Throwable e) {
System.out.println("这里有个神马异常呢 。。。" + e);
}
System.out.println("return length is " + jsonArray.length());
for (int i = 0; i < jsonArray.length(); i++) {
try {
jsonObject = jsonArray.getJSONObject(i);
String sname = jsonObject.getString("screen_name");
userNameArrayList.add(sname);
} catch (JSONException e) {
e.printStackTrace();
}
}
userName = (String[]) userNameArrayList
.toArray(new String[userNameArrayList.size()]);
adapter = new ArrayAdapter<String>(NameListActivity.this,
android.R.layout.simple_dropdown_item_1line, userName);
}
return null;
}
#Override
protected void onPostExecute(Void v) {
System.out.println("post");
editAuto.setAdapter(adapter);
}
}
void showToast(String s) {
Toast toast = Toast.makeText(getApplicationContext(), s,
Toast.LENGTH_LONG);
toast.show();
}
public class addTask extends AsyncTask<Void, Void, Void> {
String s = null;
boolean flag = false;
User user = null;
Weibo weibo = new Weibo();
String screen_name = null;
protected void onPreExecute() {
Toast tt = Toast.makeText(getApplicationContext(), "正在将用户添加到备份名单",
Toast.LENGTH_LONG);
tt.setGravity(Gravity.CENTER, 0, 0);
tt.show();
weibo.setToken(access_token);
screen_name = editAuto.getText().toString();
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
if (screen_name.length() != 0) {
Users um = new Users();
try {
user = new User(Weibo.client.get(
"https://api.weibo.com/users/show.json",
new PostParameter[] { new PostParameter(
"screen_name", screen_name) })
.asJSONObject());
} catch (Throwable e) {
e.printStackTrace();
flag = true;
s = new String("您输入的这个用户好像不存在唉");
}
if (user != null) {
ContentValues values = new ContentValues();
values.put("uid", user.getId());
values.put("user_name", user.getName());
SQLiteDatabase db = null;
try {
db = MainService.getDatabase();
} catch (Exception e) {
System.out.println("db error");
finish();
}
Cursor result = db.query("users", new String[] { "uid",
"user_name" }, "uid=?",
new String[] { user.getId() }, null, null, null);
if (result.getCount() == 0)
db.insert("users", null, values);
} else {
flag = true;
s = new String("网络存在问题,检查一下吧");
}
} else {
flag = true;
s = new String("框里输入点东西才能添加啊");
}
return null;
}
#Override
protected void onPostExecute(Void v) {
if (flag == true) {
System.out.println("要打印的是" + s);
showToast(s);
}
}
}
public class infobtnListener implements OnClickListener {
public void onClick(View v) {
// TODO Auto-generated method stub
System.out.println("点击了图片");
ColorDrawable cd = new ColorDrawable(-0000);
popupWindow.setBackgroundDrawable(cd);
// popupWindow.showAsDropDown(v);
popupWindow.showAtLocation(findViewById(R.id.informbtn),
Gravity.LEFT | Gravity.BOTTOM, 0, 100);
}
}
public class ImageListener implements OnClickListener {
public void onClick(View v) {
// TODO Auto-generated method stub
// Intent t = new Intent(NameListActivity.this,
// GridLayoutActivity.class);
// startActivity(t);
finish();
}
}
public class ChfrListListener implements OnClickListener {
public void onClick(View v) {
if ((haveInternet() == true)
&& (GridLayoutActivity.hasAccessToken() == true)) {
// TODO Auto-generated method stub
pd = ProgressDialog.show(NameListActivity.this, "",
"正在从服务器上获取数据,可能需要较长时间,请耐心等待 ...");
/* 开启一个新线程,在新线程里执行耗时的方法 */
new Thread(new Runnable() {
public void run() {
Intent t = new Intent(NameListActivity.this,
ChooseFromListActivity.class);
startActivity(t);
finish();
handler.sendEmptyMessage(0);// 执行耗时的方法之后发送消给handler
}
}).start();
} else {
Intent t = new Intent(NameListActivity.this,
WebViewActivity.class);
startActivity(t);
finish();
}
}
}
private void initPopupWindow() {
view = getLayoutInflater().inflate(R.layout.namewindow, null);
popupWindow = new PopupWindow(view, ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
// 这里设置显示PopuWindow之后在外面点击是否有效。如果为false的话,那么点击PopuWindow外面并不会关闭PopuWindow。
popupWindow.setOutsideTouchable(true);// 不能在没有焦点的时候使用
}
private boolean haveInternet() {
NetworkInfo info = ((ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE))
.getActiveNetworkInfo();
if (info == null || !info.isConnected()) {
return false;
}
if (info.isRoaming()) {
// here is the roaming option you can change it if you want to
// disable internet while roaming, just return false
return true;
}
return true;
}
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {// handler接收到消息后就会执行此方法
pd.dismiss();// 关闭ProgressDialog
}
};
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_name_list, menu);
return true;
}
}
My question is : when I input words in the EditText, nothing happened. But when I press backspace did the AutoCompleteTextView show the suggestion list ... the problem is in the editAuto.setAdapter(adapter);
What is wrong?
make the following changes in your code
1) Instead of
private AutoCompleteTextView editAuto = null; JUST WRITE private AutoCompleteTextView editAuto;
2) Add this line to onCrate()
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, <your array name here>);
and remove this line from onTextChangedTask()
ArrayList<String> userNameArrayList = new ArrayList<String>();
3) Add this line to onCrate()
editAuto.setAdapter(adapter);
I know this is way late but for those who face similar problems here is the solution to show the autoCompleteTextView's drop down whenever you want i.e on button click or onTextChanged. After you set the ArrayAdapter for the autoCompleteTextView just put the following line.
autoCompleteTextView.showDropDown();