in my app i am trying to form a grid view from the xml file that been stored in web.
Following is my code
grid = (GridView)findViewById(R.id.gridView1);
imageXMLfn();
grid.setAdapter(new ImageAdapter(this));
private void imageXMLfn()
{
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setIgnoringComments(true);
factory.setCoalescing(true);
factory.setNamespaceAware(false);
factory.setValidating(false);
DocumentBuilder parser = factory.newDocumentBuilder();
URL url = new URL(UserManual.IMAGE_URL);
Log.e("ViewImage3",""+UserManual.IMAGE_URL);
Document document= parser.parse(new InputSource(url.openStream()));
NodeList sections = document.getElementsByTagName("application");
numSections = sections.getLength();
for (int i = 0; i < numSections; i++)
{
Element section = (Element) sections.item(i);
if(section.hasChildNodes()==true)
{
NodeList section1=section.getChildNodes();
for(int j=0;j<section1.getLength();j++)
{
if(section1.item(j).hasChildNodes()==true)
{
for(int k=0;k<section1.item(j).getChildNodes().getLength();k++)
{
xmlvalue=String.valueOf(section1.item(j).getChildNodes().item(k).getNodeValue()).trim();
arl.add(xmlvalue);
}
}
}
}
}
}
catch(Exception e)
{
System.out.println(e);
Log.e("ViewImage Error1",e.getMessage());
}
Iterator<String> itr = arl.listIterator();
int z=0,x=0,increment=0;
while (itr.hasNext())
{
id = itr.next();
img = img+id;
z++;
}
}
public class ImageAdapter extends BaseAdapter
{
private Context myContext;
private String[] myRemoteImages = {id};
public ImageAdapter(Context c)
{
this.myContext = c;
}
}
Either i am getting only the first image stored in that url or else i am not getting any other images
Following is the link from which i am trying to get the images
http://94.23.207.167/websiteIphone/Admin/XML/Santa.xml
Your code is not complete, so it's a bit difficult to give a definite answer but in the while loop at the end if imageXMLfn you're assigning id = it.next(). The image adapter than uses only id which is set to the last value in the iterator. Supposing that arl is a field in your class of type ArrayList<String> it probably can be solved by:
public class ImageAdapter extends BaseAdapter
{
private Context myContext;
private String[] myRemoteImages = arl.toArray(new String[arl.size()]);
public ImageAdapter(Context c)
{
this.myContext = c;
}
}
However, your code is really incomplete in this regard, so I'm not sure whether this will work out.
What I found out mostly to this same problem is this. Lazy Load your images in the background. When in onpostexecute, don't display any images at all, due to the fact that when flinging the screen the current display then goes nuts like a multimedia slideshpw where your images blink in and out and may get updated incorrectly. Then I found that if you do a Fling detection on the gridview variable such as:
mPhotoView.setOnScrollListener(new OnScrollListener() {
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
if(scrollState != SCROLL_STATE_IDLE) {
mAdapter.setFlinging(true);
} else {
mAdapter.setFlinging(false);
}
int first = view.getFirstVisiblePosition();
int count = view.getChildCount();
if (scrollState == SCROLL_STATE_IDLE || (first + count >
mAdapter.getCount()) ) {
mPhotoView.invalidateViews();
}
}
});
the invalidateViews will cause the newly downloaded images to be refreshed. Also, on the call to the Lazy background loader, right after the process is set in motion I load a placeholder bitmap. I only now need to find a way to get a few of the leftover placeholder images that somehow find its way through on some of the scrolls to be updated when the images are available. Lazy Loaders are all over the Internet and think its a far better way to load remote images than you code above. This is one of the trickiest things Androider's try to accomplish. Took me as long as all the rest of the "gotchas" I've faced. Hope this clears things up for you. Happy coding.
Related
I am trying to implement a search function in an Android app that takes text from an AutoCompleteTextView, waits if there hasn't been made a change in the last 1.5 seconds and shows the search results. For this I use the TextWatcher class.
However, all my tries to implement this behavior ran into trouble with some functions only being allowed in the UI thread itself (via runOnUIThread) or the thread having Looper.prepare() called before.
In all attempts, the app crashes randomly when entering additional characters or deleting some, does not show any search results or reload to the start activity.
The following is a simplyfied recreation of my most recent try, where I use a Handler.
search.getResults is the long computation and matches is an array that has to be filled before delayableAdapterCreation creates the ArrayAdapterWithSpaceFilter.
public class SearchFragment extends Fragment {
public final static int MAX_NUMBER_OF_SUGGESTIONS = 4; // only show a max of 4 suggestions if more were found
public final static int SEARCH_CHAR_AMOUNT = 3; // only search if at least 3 characters were typed
public final static long SEARCH_DELAY_MILLIS = (long) 1500; // the time to wait for no text changes in milliseconds
private Search search;
private AutoCompleteTextView textView;
private String[] matches;
private String userStartRequest;
private Entry[] suggestions;
private FragmentListenter sListener;
private EntryFunctions ef = new EntryFunctions();
private Runnable delayableSearch;
private Runnable delayableAdapterCreation;
private Handler delayableSearchHandler;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
delayableSearchHandler = new Handler();
delayableSearch = new Runnable() {
#Override
public void run() {
userStartRequest = textView.getText().toString();
sListener.onFragmentFinish(userStartRequest);
suggestions = search.getResults(userStartRequest);
matches = ef.fillMatches(suggestions);
}
};
delayableAdapterCreation = new Runnable() {
#Override
public void run() {
ArrayAdapterWithSpaceFilter<String> adapter =
new ArrayAdapterWithSpaceFilter<String>(getActivity(),
android.R.layout.simple_list_item_1,
matches);
textView.setAdapter(adapter);
}
};
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_search, container, false);
}
#Override
public void onStart() {
super.onStart();
textViewHandler();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (!(context instanceof FragmentListenter)) throw new AssertionError();
sListener = (FragmentListenter) context;
}
/**
* Interface for communicate to activity
*/
public interface FragmentListenter {
void onFragmentFinish(String userStartRequest);
}
/**
* Handler for the AutoCompleteTextView
*/
private void textViewHandler() {
try {
textView = (AutoCompleteTextView) getView().findViewById
(R.id.startNaviAutoCompleteTextView);
search = new Search();
System.out.println("Created Search object");
textView.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
System.out.println("TextWatcher beforeTextChanged");
}
#Override
public void onTextChanged(CharSequence s, final int start, int before, int count) {
delayableSearchHandler.removeCallbacks(delayableSearch); userStartRequest = textView.getText().toString();
sListener.onFragmentFinish(userStartRequest);
if (textView.getText().length() >=
SEARCH_CHAR_AMOUNT) {
new Thread(delayableSearch).start();
delayableSearchHandler.postDelayed
(delayableAdapterCreation, SEARCH_DELAY_MILLIS);
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
At this point, it does not matter to me, whether the calculation already starts whenever a new character is typed into the AutoCompleteTextView and an eventual old search is canceled or the search starts after the 1.5 seconds.
The above code does crash if the search term yields no results and there are problems with the results list. Sometimes it shows up for what has been entered a few keystrokes ago (so if I search for abcd slowly I get search results for abc), sometimes it doesn't show up at all. My guess would be a race condition or some problem with calling the textViewHandler or onTextChanged methods multiple times, even though delayableSearchHandler.removeCallbacks(delayableSearch) should prevent this from happening.
Can anyone explain, what the interaction between the worker thread and the UI thread would have to look like, so it is guaranteed that the search delivers it's results?
Thanks in advance,
Joe
Any long running operation (Network call, database search...) can take long time to execute thus blocking the UI. Prior to Ice cream sandwich this kind of behavior was tolerated by the android runtime.
This article might be a good read
I am making a simple game that uses GridView and a custom Adapter. It is basically a game that player can move through the GridView (simply changing the images of cells). The game has 10 levels. Problem is, when I get out of the activity (e.g. going back to the MainActivity) the game is reset. Also naturally when phone is turend off and on the game is reset.
I want to preserve the game state so when the player enters the GameActivity, he/she can continue with the game.
I only require 3 things to be saved, the Adapter, number of Level and the available moves. Simply if I knew how to work this out I could achieve what I need:
public class GameState implements Serializable {
private GameAssetAdapter mAdapter;
private int mLevel;
private int mAvailableMoves;
public GameState(GameAssetAdapter adapter, int level, int availableMoves) {
mAdapter = adapter;
mLevel = level;
mAvailableMoves = availableMoves;
}
public GameAssetAdapter getAdapter() {
return mAdapter;
}
public int getLevel() {
return mLevel;
}
public int getAvailableMoves() {
return mAvailableMoves;
}
}
So the question is, how can I save this object to internal storage and retrive it back when necessary?
I already have tried the onSaveInstanceState but it does not work as expected. phone off/on will reset this. Even if user wipes the app in the app list of android it will be reset. What should I do?
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(AppConstants.GAME_SAVE_ASSET_ADAPTER, mGameAssetAdapter);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
if(savedInstanceState != null)
{ //Restore mGameAssetAdapter if was saved perviously
if(mGameAssetAdapter == null){
restoreGameAssetAdapter(savedInstanceState);
}
}
//TODO get level and states!!
mGameGridView = (GameGridView)findViewById(R.id.game_grid_view);
mGameGridView.setNumColumns(GameConstants.COLUMNS);
mGameGridView.setColumnWidth(GameHelper.getOptimumAssetImageWidth(this,
GameConstants.COLUMNS));
if(mGameAssetAdapter == null) {
mGameAssetAdapter = new GameAssetAdapter(this, mLevel);
}
mGameGridView.setAdapter(mGameAssetAdapter);
this.setTitle("Snakes and Ladders - Level " + mLevel);
setupEvents();
}
private void restoreGameAssetAdapter(Bundle savedInstanceState) {
if(savedInstanceState.getSerializable("GAME_ASSET_ADAPTER") != null){
mGameAssetAdapter =
(GameAssetAdapter) savedInstanceState.
getSerializable("GAME_ASSET_ADAPTER");
Log.v(TAG, "Restored saved GameAssetAdapter! Hoooray!");
}
}
You can just write the state to storage. Here is some code from my personal stash:
private static byte[] readBytes(String dir, Context context) throws IOException
{
FileInputStream fileIn = null;
DataInputStream in = null;
byte[] buffer = null;
fileIn = context.openFileInput(dir);
in = new DataInputStream(fileIn);
int length = in.readInt();
buffer = new byte[length];
for(int x = 0;x < buffer.length;x++)
buffer[x] = in.readByte();
try
{
fileIn.close();
} catch (Exception e) {}
try
{
in.close();
} catch (Exception e) {}
fileIn = null;
in = null;
return buffer;
}
private static void writeBytes(String dir, byte bytes[], Context context) throws IOException
{
FileOutputStream fileOut = null;
DataOutputStream out = null;
fileOut = context.openFileOutput(dir, Context.MODE_PRIVATE);
out = new DataOutputStream(fileOut);
int length = bytes.length;
out.writeInt(length);
out.write(bytes);
out.flush();
try
{
fileOut.close();
} catch (Exception e) {}
try
{
out.close();
} catch (Exception e) {}
}
You can save your state by using the writeBytes() method, then when the app is relaunched, all you have to do is use readBytes() to restore the game state.
If I may make one small structural suggestion, I like to make a 'package' class that holds my state variables when I write it to disk like this:
public class SavedState implements Serializible
{
public GameState state;
int id;
...
}
Then when you write this to disk, you will have all of your state variables in one clean class. I would also recommend not saving your DisplayAdapter for your list view (you might have a lot of problems) or whatever it is. Save the underlying data structure to this package class and then create a new DisplayAdapter when you resume the app state.
If you don't know how to turn an object into a byte array, here is the SO question for it:
Java: object to byte[] and byte[] to object converter (for Tokyo Cabinet)
I am trying to speak out large amount of text using Android Text To Speech. I using default Google speech engine. Below is my code.
public class Talk extends Activity implements TextToSpeech.OnInitListener {
private ImageView playBtn;
private EditText textField;
private TextToSpeech tts;
private boolean isSpeaking = false;
private String finalText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_talk);
//Intialize the instance variables
playBtn = (ImageView)findViewById(R.id.playBtn);
textField = (EditText)findViewById(R.id.textField);
//Resister the listeners
playBtn.setOnClickListener(new PlayBtnAction());
//Other things
tts = new TextToSpeech(this,this);
//Get the web page text if called from Share-Via
if (Intent.ACTION_SEND.equals(getIntent().getAction()))
{
new GetWebText().execute("");
}
}
//This class will execute the text from web pages
private class GetWebText extends AsyncTask<String,Void,String>
{
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
String text = getIntent().getStringExtra(Intent.EXTRA_TEXT);
String websiteText = "";
try {
//Create a URL for the desired page
URL url = new URL(text);
// Read all the text returned by the server
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String str;
StringBuffer strBuffer = new StringBuffer("");
while ((str = in.readLine()) != null)
{
strBuffer.append(str+"\n"+"\n");
}
in.close();
String html = strBuffer.toString();
Document doc = Jsoup.parse(html);
websiteText = doc.body().text(); // "An example link"
//Toast.makeText(this, websiteText, Toast.LENGTH_LONG).show();
}
catch(Exception e)
{
Log.e("web_error", "Error in getting web text",e);
}
return websiteText;
}
#Override
protected void onPostExecute(String result)
{
textField.setText(result);
}
}
}
//Class to speak the text
private class PlayBtnAction implements OnClickListener
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
if(!isSpeaking)
{
isSpeaking = true;
//speak(textField.getText().toString());
finalText = textField.getText().toString();
new SpeakTheText().execute(finalText);
isSpeaking = false;
}
else
{
isSpeaking = false;
tts.stop();
}
}
}
#Override
public void onInit(int status) {
// TODO Auto-generated method stub
if(status==TextToSpeech.SUCCESS)
{
int result = tts.setLanguage(Locale.UK);
if(result==TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED)
{
Toast.makeText(this, "Language Not Supported", Toast.LENGTH_LONG).show();
}
}
}
//This class will speak the text
private class SpeakTheText extends AsyncTask<String,Void,String>
{
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
tts.speak(params[0], TextToSpeech.QUEUE_FLUSH, null);
return null;
}
}
#Override
public void onDestroy()
{
if(tts!=null)
{
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
}
But the issue here is, when there is a large chunk of text (lets say you have extracted text from a web page) the TTS fails to read it. If I remove most of the text, then it will read it. Why is this happening?
When I am about to read the large text, the LogCat however display something like this
10-11 07:26:05.566: D/dalvikvm(2638): GC_CONCURRENT freed 362K, 44% free 3597K/6312K, paused 17ms+8ms, total 93ms
The String length should not be longer than pre-defined length, from docs:
Parameters
text The string of text to be spoken. No longer than getMaxSpeechInputLength() characters.
Returned value by getMaxSpeechInputLength() may vary from device to device, but according to AOSP source that is whopping 4000:
/**
* Limit of length of input string passed to speak and synthesizeToFile.
*
* #see #speak
* #see #synthesizeToFile
*/
public static int getMaxSpeechInputLength() {
return 4000;
}
Try not to exceed that limit: compare input text length with that value and split into separate parts if necessary.
Use this code...Working for any file ..
just send the string to speech function..
private void speech(String charSequence) {
int position ;
int sizeOfChar= charSequence.length();
String testStri= charSequence.substring(position,sizeOfChar);
int next = 20;
int pos =0;
while(true) {
String temp="";
Log.e("in loop", "" + pos);
try {
temp = testStri.substring(pos, next);
HashMap<String, String> params = new HashMap<String, String>();
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, temp);
engine.speak(temp, TextToSpeech.QUEUE_ADD, params);
pos = pos + 20;
next = next + 20;
} catch (Exception e) {
temp = testStri.substring(pos, testStri.length());
engine.speak(temp, TextToSpeech.QUEUE_ADD, null);
break;
}
}
}
In case someone might find this helpful. When you split the large text into strings, do not set the length of each string to the exact value of getMaxSpeechInputLength(). Subtract the string length by 1. Otherwise, only the last chunk of string could be read by TTS.
int length = toSpeech.getMaxSpeechInputLength() - 1;
Iterable<String> chunks = Splitter.fixedLength(length).split(largeText);
Lists.newArrayList(chunks);
It is worse than the 4000 characters limit in practice on Android. There are some TTS engines that limit the input length a lot more. For example Nuance.tts and vocalizer.tts engines won't speak any string longer than about 512 characters (from my tests some time ago). Today I hit a limit of below 300 characters in es.codefactory.eloquencetts package, which simply crashes if the string I send to it is more than 256-300 characters. I divide the contents into sentences, and guard for sentences longer than the above limit, further sub-dividing them in my app code.
Greg
If you follow ozbek's advice you should be fine. I too have large text files that I want spoken. I simply used the streamreader method and everything works fine. heres' PART of my code. it's the part that you should use. My code does a bit more than you want but it works for me and may work for you.
Dim sReader As StreamReader = New StreamReader(Story_file)
Try
Do Until EndOfStream '= True
Dim line_to_speak As String = sReader.ReadLine
Dim vc = Mid(line_to_speak, 1, 1) <- you dont need this
Select Case vc <- you dont need this
Case Is = "/" <- you dont need this
voice_index = Val(Mid(line_to_speak, 2, 2)) <- you dont need this
srate = Val(Mid(line_to_speak, 5, 2)) <- you dont need this
edassistv.lstVoices.SelectedIndex = voice_index <- you dont need this
selected_voice = edassistv.lstVoices.SelectedItem <- you dont need this
Case Else<- you dont need this
synth.SelectVoice(selected_voice)
synth.Speak(line_to_speak)
End Select<- you dont need this
Loop
Catch ex As Exception
GoTo finish
What I want to do: get the id of the src of an ImageView, compare it to the ids of two drawables, and swap them, using AsyncTask (just because I want to understand how it works).
I've read similar questions here, and so far this is what I've got:
public class Main extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView image = (ImageView) findViewById(R.id.img);
Integer integer = (Integer) image.getTag();
}
private class cambiarImagen extends AsyncTask<Integer, Integer, Integer> {
protected void onPreExecute() {
ImageView image = (ImageView) findViewById(R.id.img);
Integer integer = (Integer) image.getTag();
int img1 = R.drawable.zapato;
int img2 = R.drawable.zapatod;
}
#Override
protected Integer doInBackground(Integer... values) {
// parte logica
int num = values[0];
int zapato = values[1];
int zapatod = values[2];
if (num == zapato) {
num = zapatod;
} else if (num == zapatod) {
num = zapato;
}
return num;
}
protected Void onPostExecute(Integer... values) {
int num = values[0];
ImageView image = (ImageView) findViewById(R.id.img);
image.setTag(num);
return null;
}
}
Of course this doesn't work.
1. I don't understand how to get the id of the drawable that ImageView has as its src.
2. I don't understand how the params are passed in AsyncTask; onPreExecute should receive the UI stuff, doInbackground should receive it to compare it and return the drawable int that should be set to the ImageView, and onPreExecute should set it to the ImageView.
I don't understand how to get the id of the drawable that ImageView has as its src.
I haven't had to do this so may not work but you should be able to use
imageView.getDrawable().getId();
I don't understand how the params are passed in AsyncTask;
Whatever you pass in task.execute() is received by doInBackground(). If you call publishProgress() then whatever params are sent there are received by onProgressUpdate(). And the data returned in doInBackground() is received by onPostExecute().
AsyncTask, just so you know, shouldn't be needed for this but I know you said you wanted to learn how to use it. I was a little confused on exactly what specifically you were having trouble with besides these two things so please elaborate if I missed something.
ImageView Docs
AsyncTask Docs
AsyncTask Example (in case it can be helpful)
You should do other task if you like to get to learn ASyncTask.
I would have done a dialog with progress bar or something instead if i wanted to learn ASyncTask.
edit:
As Samus Arin comment on the main post about you should always have track on which image that you are showing. so instead use something like
if(currentImage == R.Drawable.image1){
image.setImageResource(R.Drawable.image2);
}else{
image.setImageResource(R.Drawable.image1);
}
For what it's worth, take a look at what I'm doing with an AsyncTask, maybe it'll give ya some ideas.
This is Monodroid/C# code, not raw Java/Android (but the syntax is extremely close). As such, inner-classes do not get an implicit reference to their containing object, and so I pass one in (called outer in the constructor). I chose to name it "_" as a lexicographical extension to .NET's _member naming convention for private data members.
public class MonthChangeTask : AsyncTask
{
private CalendarView _; // outer class
private DateTime _newMonth;
private bool _refreshInspectionRecordsRemote;
private bool _changingInspector;
private bool _todayButtonPressed;
private Android.App.ProgressDialog _progressDialog;
private IMXController _controller;
private Dictionary<string, string> _paramz;
private DateTime _newSelectedDate;
public MonthChangeTask( CalendarView outer, DateTime newMonth, bool changingInspector, bool refreshInspectionRecordsRemote, bool todayButtonPressed )
{
_ = outer;
_newMonth = newMonth;
_changingInspector = changingInspector;
_refreshInspectionRecordsRemote = refreshInspectionRecordsRemote;
_todayButtonPressed = todayButtonPressed;
}
protected override void OnPreExecute()
{
base.OnPreExecute();
_progressDialog = Android.App.ProgressDialog.Show( _ , "", "Loading Inspections...");
_newSelectedDate = _._calendar.SetMonth(new DateTime(_newMonth.Year, _newMonth.Month, 1));
AppSettingService.SetCalendarDate(_newMonth);
_paramz = new Dictionary<string, string>();
string target = MD.MxNAVIGATION.CONTROLLER.CALENDAR._name;
string action = MD.MxNAVIGATION.CONTROLLER.ACTION.GET;
string command = _refreshInspectionRecordsRemote
? ((int) MD.MxNAVIGATION.CONTROLLER.CALENDAR.Command.RefreshInspectionRecordsRemote).ToString()
: ((int) MD.MxNAVIGATION.CONTROLLER.CALENDAR.Command.RefreshInspectionRecordsLocal).ToString();
string url = target + "/" + action + "/" + command;
_controller = MXContainer.Instance.GetController(url, ref _paramz);
}
protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] #params)
{
if ( _paramz == null )
{
Log.Info(FIDB.TAG_APP, "MonthChangeTask.DoInBackground(): paramz = NULL");
}
else
{
_controller.Load( _paramz );
}
return true;
}
protected override void OnPostExecute(Java.Lang.Object result)
{
base.OnPostExecute(result);
_progressDialog.Dismiss();
_.Model = (CalendarVM)_controller.GetModel();
if (_changingInspector)
{
_._calendar.PermitSwitch = _.Model.Buttons.PermitsVisible;
_._calendar.ComplaintSwitch = _.Model.Buttons.ComplaintsVisible;
_._calendar.ProjectSwitch = _.Model.Buttons.ProjectsVisible;
_._calendar.PeriodicInspectionSwitch = _.Model.Buttons.PeriodicInspectionsVisible;
}
_.UpdateCalendar(_.Model.Inspections);
if( _todayButtonPressed )
{
_._calendar.SelectedDate = _._calendar.CurrentDate;
}
else
{
_._calendar.SelectedDate = _newSelectedDate;
}
_._calendar.Invalidate();
AppSettingService.SetCalendarDate( _._calendar.SelectedDate );
if ( _.Model.IsParcelCacheDownloading )
{
AnimationTask task = new AnimationTask( _ );
task.Execute( new Java.Lang.Object[1] );
}
}
}
I have implemented a listview in which data is loaded through an asynctask, To load more data I have used this code found here (exactly copy pasted)
Main Activity
class load_data extends AsyncTask<Integer, Void, Void>{
// This asynctask takes in a page number as argument and depending on that page number
// data is loaded and stored in various String[] arrays and their length is extended as new items are loaded
protected void onPostExecute(Void result) {
if(adapter == null){
adapter = new Listadapter(Main.this,String[],String[],String[]);
list.setAdapter(adapter);
}
else if(adapter != null){
adapter.notifyDataSetChanged();
}
}
}
This task is called as new load_data().execute(1);
after this code I have the load more data snippet from the above link
everything works perfectly no syntax errors, and also the data loads after reacing the given threshold (20) in my case, however new data is not shown. how do I notifiy the adapter that more data has been added or data has been changed
Thanks!.
EDIT: LOADMORE CLASS
class EndlessScrollListener implements OnScrollListener {
private int visibleThreshold = 5;
private int currentPage = 1;
private int previousTotal = 0;
private boolean loading = true;
public EndlessScrollListener() {
}
public EndlessScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
currentPage++;
}
}
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
// I load the next page of gigs using a background task,
// but you can call any function here.
new load_data().execute(currentPage);
adapter.notifyDataSetChanged();
loading = true;
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
}
list.setOnScrollListener(new EndlessScrollListener(20)); // 20 being the threshold
Finally! for those who are stuck with the same problem, I have the solution.
I have noticed that adapter.notifyDataSetChanged(); does not work if you are using String[] arrays to store data which is displayed into the listview rows.
Instead if you use List<String> list = new ArrayList<String>();and store data in the
the listview will be updated with new data :)
you can check this github project if you have any problem with your previous code.
otherwise if you want to load data like pagination you can try this example and this one