I just about got this, but I have a small problem in the order of things going off. Specifically, in my thread() I am setting up an array that is used by a Spinner. Problem is the Spinner is all set and done basically before my thread() is finished, so it sets itself up with a null array.
How do I associate the spinners ArrayAdapter with an array that is being loaded by another thread?
I've cut the code down to what I think is necessary to understand the problem, but just let me know if more is needed. The problem occurs whether or not refreshData() is called.
Along the same lines, sometimes I want to call loadData() from the menu. Directly following loadData() if I try to fire a toast on the next line this causes a forceclose, which is also because of how I'm implementing ProgressDialog.
THANK YOU FOR LOOKING
public class CMSHome extends Activity {
private static List<String> pmList = new ArrayList<String>();
// Instantiate helpers
PMListHelper plh = new PMListHelper();
ProjectObjectHelper poc = new ProjectObjectHelper();
// These objects hold lists and methods for dealing with them
private Employees employees;
private Projects projects;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Loads data from filesystem, or webservice if necessary
loadData();
// Capture spinner and associate pmList with it through ArrayAdapter
spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
this, android.R.layout.simple_spinner_item,
pmList);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
//---the button is wired to an event handler---
Button btn1 = (Button)findViewById(R.id.btnGetProjects);
btn1.setOnClickListener(btnListAllProjectsListener);
spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
}
private void loadData()
{
final ProgressDialog pd = ProgressDialog.show(this,
"Please wait", "Loading Data...", true, false);
new Thread(new Runnable(){
public void run(){
employees = plh.deserializeEmployeeData();
projects = poc.deserializeProjectData();
// Check to see if data actually loaded, if not then refresh
if ((employees == null) || (projects == null)) {
refreshData();
}
// Load up pmList for spinner control
pmList = employees.getPMList();
pd.dismiss();
}
}).start();
}
private void refreshData()
{
// Refresh data for Projects
projects = poc.refreshData();
poc.saveProjectData(mCtx, projects);
// Refresh data for PMList
employees = plh.refreshData();
plh.savePMData(mCtx, employees);
}
}
<---- EDIT -----> I tried changing onCreate() to the following after Jims suggestion. Not sure if I did this right, still doesn't work:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mCtx = this;
// Loads data from filesystem, or webservice if necessary
// Would like to extend this to update if files are over x days old
final ProgressDialog pd = ProgressDialog.show(this,
"Please wait", "Loading Data...", true, false);
new Thread(new Runnable(){
public void run(){
employees = plh.deserializeEmployeeData();
projects = poc.deserializeProjectData();
// Check to see if data actually loaded, if not then refresh
if ((employees == null) || (projects == null)) {
refreshData();
}
pd.dismiss();
runOnUiThread(new Runnable() {
public void run(){
// Load up pmList for spinner control
pmList = employees.getPMList();
}
});
}
}).start();
spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
this, android.R.layout.simple_spinner_item, pmList);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
//---the button is wired to an event handler---
Button btn1 = (Button)findViewById(R.id.btnGetProjects);
btn1.setOnClickListener(btnListAllProjectsListener);
spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
}
Wow, this took forever for me to find a solution, but Im overjoyed to have finally gotten this to work.
Updating the Spinner with a background thread can be accomplished by utilizing a handler. The handler is called after the main work of the thread is completed.
mProgressDlg = ProgressDialog.show(this, "App_Name", "Loading data...",
true, false);
new Thread(new Runnable(){
public void run() {
/*Load Data, set pmList in my case*/
mProgressDlg.dismiss();
hRefresh.sendEmptyMessage(REFRESH);
}
}).start();
Handler hRefresh = new Handler(){
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case REFRESH:
spinner = (Spinner) findViewById(R.id.spinner);
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
mCtx, android.R.layout.simple_spinner_item, pmList);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
break;
}
}
};
Credit to bhatt4982 and his answer on this thread
Don't know if you've ever solved this, but this works for me:
I would also suggest you to use https://github.com/commonsguy/cwac-task it has very nice AsyncTaskEx impl, which you can use to do heavy work without locking the ui.
Example class;
from your main activity you can call like this;
All the work after loadData() in onCreate() needs to be done after the work in run() in the thread triggered in loadData() has been completed. Try inlining loadData(), and adding this post-setup work to a runOnUiThread() after pd.dismiss().