How do I set up my doInBackground's params in my AsyncTask? - android

my screen when I click on a button is slow to load (because of downloading images? the image files are really small though) so I tried to use AsyncTask to help. The program works, but I moved the image loading to an AsyncTask to see if it would load faster and the app crashes every time. I'm guessing it has to do with the way I have it set up. How would I fix it? Would using a runnable thread be better instead? Thanks!
The class:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// no title
requestWindowFeature(Window.FEATURE_NO_TITLE);
// set full screen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// inflate listview
setContentView(R.layout.gmg);
**new Load.execute(); // executes AsyncTask**
...
gmgListView = (ListView) findViewById(R.id.gmg_list2);
GMGListViewAdapter adapter = new GMGListViewAdapter(this,
R.layout.gmg_list_row, rowItems);
gmgListView.setAdapter(adapter);
gmgListView.setOnItemClickListener(this);
}
The AsyncTask:
private class Load extends AsyncTask<String, Void, Void> {
private ProgressDialog Dialog = new ProgressDialog(GMGListViewActivity.this);
#Override
protected void onPreExecute() {
Dialog.setMessage("Doing something...");
Dialog.show();
}
#Override
protected Void doInBackground(String... params) {
SparseArray<Spanned> gmgText = null;
Integer[] right = null;
SparseArray<Drawable> appIcon = null;
try {
gmgText = ParseContent.queryGMGText();
right = ParseContent.queryGMGRight();
appIcon = ParseContent.queryDrawable();
} catch (ParseException e) {
e.printStackTrace();
}
// Inflate GMG's rows
rowItems = new ArrayList<GMGRowItem>();
for (int i = 0; i < gmgText.size(); i++) {
GMGRowItem item = new GMGRowItem(appIcon.get(i), gmgText.get(i), right[i]);
rowItems.add(item);
}
return null;
}
protected void onPostExecute(Void unused) {
Dialog.dismiss();
}
}

You need to apply some changes in your code like...
need to set list adapter in onPostExecute method and remove it from onCreate().
After completing background process it will interact with ui thread.
protected void onPostExecute(Void unused) {
Dialog.dismiss();
GMGListViewAdapter adapter = new GMGListViewAdapter(this,
R.layout.gmg_list_row, rowItems);
gmgListView.setAdapter(adapter);
}
Try this and let me know if you got any isssue.

Related

Start something when Listview is filled

I have a ListView which displays images from my cloud.
There may be a delay between when my user open the activity with the ListView and when the ListView is populated with the images.
For example if the user do not have the Internet connection on, the images won't be displayed.
I'd like to change several things on my UI (add a button, start an animation...) only when the ListView is filled. I guess I should use a listener to know when the ListView is not empty or when my EmptyView visibility is gone. Here are the two solutions I tried :
Solution 1:
myListview.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
#Override
public void onSystemUiVisibilityChange(int i) {
if (myListview.getVisibility() == View.VISIBLE){
//UI changes here
Solution 2 :
if (listviewAdapter != null){
...UI changes here
None of these solutions work, and I cannot find another one. Any idea ?
Thank you !
You can set a timer for this approach. For example wait for 5 seconds or 10 seconds and check if the listView is populated or not if yes then show what ever you want else do not show.
final Timer timer2 = new Timer();
timer2.schedule(new TimerTask() {
public void run() {
if(listViewCount>0)
{
//do your stuff
}
}
}, 5000);
Use AsyncTask class like this:
...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
if(checkConnexion()){ showToast("No Connexion"); }
else{ new loadImage().execute(); }
}
class loadImage extends AsyncTask<Void, Void, Void> {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
/* show ProgressDialog before doing anything*/
dialog = ProgressDialog.show(getApplicationContext(), "Veuillez patienter", "Chargement des données....", true);
}
#Override
protected Void doInBackground(Void... param) {
try {
/* load your images into ArrayList for example */
} catch (Exception e) {
e.printStackTrace();
dialog.dismiss();
}
return null;
}
#Override
protected void onPostExecute(Void res) {
/* ** Update your UI here ***
if size of ArrayList >0 initial your adapter
listView.setAdapter(adapter);
else showToast("Erreur loading ...");
****hide ProgressDialog after finishing*** */
dialog.dismiss();
}}
private void showToast(String msg){Toast.makeText(getApplicationContext(),msg, Toast.LENGTH_SHORT).show();}

Android loading listview with progress dialog

this is my code to load listview items
#SuppressLint("DefaultLocale")
public class SearchList extends Activity {
private ArrayList<String> founded = new ArrayList<String>();
private OrderAdapter m_adapter;
ListView lv;
/** Called when the activity is first created. */
#SuppressLint("DefaultLocale")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.searchlist);
lv = (ListView) findViewById(R.id.listView1);
new Load().execute();
m_adapter = new OrderAdapter(this, R.layout.itemview, founded);
lv.setAdapter(m_adapter);
lv.setTextFilterEnabled(true);
}
private class Load extends AsyncTask<Void, Void, Void> {
ProgressDialog progress;
#Override
protected void onPreExecute() {
progress = new ProgressDialog(SearchList.this);
progress.setMessage("loading....");
progress.show();
}
#Override
protected Void doInBackground(Void... params) {
try {
for (int i = 0; i <500000; i++) {
founded.add("String "+i);
}
} catch (Exception e) {
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// write display tracks logic here
progress.dismiss(); // dismiss dialog
}
}
when i run the code the progress dialog already appear but after its dismiss i found that the list is empty no items added to it i do not know what is the problem and why the list is empty after the dialog loading .Pls need help
thanks in advance.
Set listadapter in onPostExecute Because you Are using AsyncTask to get adapter data and setting ListAdapter before Completing AsyncTask So Try to Set ListAdapter after Completing AsyncTask
So add these
m_adapter = new OrderAdapter(this, R.layout.itemview, founded);
lv.setAdapter(m_adapter);
lv.setTextFilterEnabled(true);
lines in onPostExecute method instead of onCreate Method
#Override
protected void onPostExecute(Void result) {
// write display tracks logic here
progress.dismiss(); // dismiss dialog
m_adapter = new OrderAdapter(YourActivity.this, R.layout.itemview, founded);
lv.setAdapter(m_adapter);
lv.setTextFilterEnabled(true);
}

how to save data in a listView and scroll position while navigating between activities

I have an Activity that extends a ListActivity , in onCreate method i set the contentView and call an AsyncTask to load data and the list get filled as I want, the problem is when I check for example the detail activity and want go back the the listView: I get the onCreate method executed, data are loaded again and the listView is scrolled to the top loosing my previous position.
What I want to achieve is something like google gmail app for example: the list view get loaded once and the scroll position is saved.
I've looked so much over here and I tried many solutions but none is working.
What is the best way to achieve this scenario?
my activity :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
new LoadEvents().execute();
}
my asyncTask :
class LoadEvents extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(Home.this);
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
protected String doInBackground(String... args) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
JSONObject json = jParser.makeHttpRequest(AgendaIConstantes.URL_EVENTS, "GET", params);
......Processing
eventList.add(map);
}
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String file_url) {
pDialog.dismiss();
runOnUiThread(new Runnable() {
public void run() {
ListAdapter adapterRes = getListAdapter();
if(adapterRes == null){
ListAdapter adapter = new SimpleAdapter(Home.this, eventList,R.layout.list_item,
new String[] { .....},
new int[] { .....});
setListAdapter(adapter);
}
}
});
}
Just do not execute your loading task every call of onCreate method. You can use either boolean flag in your activity or save state using onSaveInstanceState.
By the way, calling getListAdapter in onPostExecute is not very ok method and your null checking shows it.

android html parsing with jsoup

Trying to parse an html pages like http://www.ts.kg/serials/ on android. Tried to do it with htmlcleaner, but it didnot work. Trying to do it with jsoup. In the begining was my code to complex. Here is the shortest code. The same thing works on java Please help. My Logs http://smartpics.kz/imgs/1361209668WW5O.JPG
Here is my class:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] names= {};
String url = "http://www.ts.kg/mults/";
try {
Document doc = Jsoup.connect(url).get();
Element e = doc.body();
Elements ggg = e.getElementsByAttributeValue("class", "categoryblocks");
for (int i =0;i<ggg.size();i++) {
Element linkk = ggg.get(i);
if(linkk.getElementsByTag("a")!=null){
Element atom = linkk.getElementsByTag("a").first();
String n = atom.getElementsByTag("span").first().text();
names[i] = n;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ListView lvMain = (ListView) findViewById(R.id.listViewData);
// создаем адаптер
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, names);
// присваиваем адаптер списку
lvMain.setAdapter(adapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
posted 20.feb.2013:
tryed to do it as it was proposed by Shoshy (thanks for your answer), but it didn't work (perhaps because of my not-from-right-place-growing hands). Here is my modified code:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
url = "http://www.ts.kg/mults/";
pd = ProgressDialog.show(MainActivity.this, "Working...", "request to server", true, false);
//Запускаем парсинг
new AsyncExecution().execute();
}
private ProgressDialog pd;
String url;;
String names[];
private class AsyncExecution extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
// here your task will be done in seperate thread from UI thread
// and if you want to use the variables (that will be modifed here)
// from anywhere in MainActivity, then you should declare them as global
// variable in MainActivity. remember you cannot update UI from here , like
// Toast message. if you want to do that you can use OnPostExecute
// method bellow .
try {
ArrayList<String> array = new ArrayList<String>();
Document doc = Jsoup.connect(url).get();
Element e = doc.body();
Elements ggg = e.getElementsByAttributeValue("class", "categoryblocks");
for (int i =0;i<ggg.size();i++) {
Element linkk = ggg.get(i);
if(linkk.getElementsByTag("a")!=null){
Element atom = linkk.getElementsByTag("a").first();
String n = atom.getElementsByTag("span").first().text();
array.add(n);
}
}
for (int i = 0;i<array.size();i++){
names[i]=array.get(i);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
//Убираем диалог загрузки
pd.dismiss();
//Находим ListView
ListView listview = (ListView) findViewById(R.id.listViewData);
//Загружаем в него результат работы doInBackground
listview.setAdapter(new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1, names));
}
}
}
you have to make the request for getting the page in another thread from UI thread. you can use AsyncTask. i am giving some example by editing your code :
the link about AsyncTask is : about AsynckTask
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//the class is defined bellow
new AsyncExecution().execute();
//other codes.....
.......................
}
/// your other codes .....
// you need to add this class
private class AsyncExecution extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
// here your task will be done in seperate thread from UI thread
// and if you want to use the variables (that will be modifed here)
// from anywhere in MainActivity, then you should declare them as global
// variable in MainActivity. remember you cannot update UI from here , like
// Toast message. if you want to do that you can use OnPostExecute
// method bellow .
try {
Document doc = Jsoup.connect(url).get();
Element e = doc.body();
Elements ggg = e.getElementsByAttributeValue("class", "categoryblocks");
for (int i =0;i<ggg.size();i++) {
Element linkk = ggg.get(i);
if(linkk.getElementsByTag("a")!=null){
Element atom = linkk.getElementsByTag("a").first();
String n = atom.getElementsByTag("span").first().text();
names[i] = n;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected void onPostExecute(Void result) {
}
}

Can't set ListView Adapter from AsyncThread

I'm using a ListView on my Activity and it takes a while to load from a SQLite DB, so I wanted to show a ProgressDialog to the user to let them know something is loading. I tried to run the task on a separate thread but I'm getting a CalledFromWrongThreadException. Here's my main Activity code:
#Override
public void onCreate(Bundle savedInstanceState)
{
try
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.open_issues);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);
//Set Window title.
final TextView title = (TextView) findViewById(R.id.customTitle);
if (title != null)
title.setText("Open Issues");
//Call Async Task to run in the background.
new LoadIssuesTask().execute();
}
catch (Exception e)
{
Errors.LogError(e);
}
}
And the LoadIssuesTask code:
private class LoadIssuesTask extends AsyncTask<Void, Void, Cursor> {
ProgressDialog pdDialog = null;
protected void onPreExecute()
{
try
{
pdDialog = new ProgressDialog(OpenIssues.this);
pdDialog.setMessage("Loading Issues and Activities, please wait...");
pdDialog.show();
}
catch (Exception e)
{
Errors.LogError(e);
}
}
#Override
protected Cursor doInBackground(Void... params) {
LoadIssues();
return null;
}
#Override
protected void onPostExecute(Cursor c) {
pdDialog.dismiss();
pdDialog = null;
}
}
And the LoadIssues code:
private void LoadIssues(){
//Set listview of Issues.
ListView lvIssues = (ListView)findViewById(R.id.lvIssues);
lvIssues.setOnItemClickListener(viewIssuesListener);
IssueCreator = new IssueInfoCreator(this, Integer.parseInt(AppPreferences.mDBVersion));
IssueCreator.open();
lvIssues.setAdapter(new IssueInfoAdapter(this, IssueCreator.queryAll()));
IssueCreator.close();
}
Constructor for IssueInfoAdapter:
public IssueInfoAdapter(Context c, List<IssueInfo> list){
mListIssueInfo = list;
//create layout inflater.
mInflater = LayoutInflater.from(c);
}
It's throwing the error on the .setAdapter method inside LoadIssues().
ERROR:
03-12 10:41:23.174: E/AndroidRuntime(11379): Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
You're trying to access the views in the doInBackground method that doesn't run on the main UI thread. You'll have to set your adapter in the method onPostExecute that runs on the UI thread:
#Override
protected void onPostExecute(List<IsueInfo> items) {
pdDialog.dismiss();
ListView lvIssues = (ListView)findViewById(R.id.lvIssues);
lvIssues.setOnItemClickListener(viewIssuesListener);
lvIssues.setAdapter(new IssueInfoAdapter(this, items));
}
and in your doInBackground method:
#Override
protected List<IssueInfo> doInBackground(Void... params) {
IssueCreator = new IssueInfoCreator(this, Integer.parseInt(AppPreferences.mDBVersion));
IssueCreator.open();
IssueCreator.close();
return IssueCreator.queryAll();
}
Also your AsyncTask should be:
private class LoadIssuesTask extends AsyncTask<Void, Void, List<IssueInfo>>
In private void LoadIssues method call handler.setMessage(0) and create a private Handler instance to call setAdapter method
Use Handler instead of Asynctask.

Categories

Resources