J'ai à peu près cela, mais j'ai un petit problème dans l'ordre des choses qui se passe. Plus précisément, dans mon thread() je configure un tableau qui est utilisé par un Spinner. Le problème est que le Spinner est tout réglé et fait avant que mon thread() soit fini, donc il s'installe avec un tableau nul. Comment associer les spinner ArrayAdapter à un tableau chargé par un autre thread?Android ProgressDialog barre de progression de faire les choses dans le bon ordre
J'ai réduit le code à ce que je pense est nécessaire pour comprendre le problème, mais laissez-moi savoir si plus est nécessaire. Le problème se produit si refreshData() est appelé ou non. Dans le même ordre d'idées, parfois je souhaite appeler loadData() depuis le menu. Directement après loadData() si j'essaie de lancer un toast sur la ligne suivante cela provoque un forceclose, qui est aussi à cause de la façon dont j'applique ProgressDialog.
MERCI POUR LE REGARD
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> Je essayé de changer onCreate() à ce qui suit après la suggestion JIM. Je ne sais pas si je l'ai fait ce droit, ne fonctionne toujours pas:
@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, cela a pris une éternité pour moi de trouver une solution, mais je suis fou de joie d'avoir enfin obtenu cela fonctionne.
La mise à jour du Spinner avec un fil d'arrière-plan peut être effectuée en utilisant un gestionnaire. Le gestionnaire est appelé après que le travail principal du thread est terminé.
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;
}
}
};
Crédit bhatt4982 et sa réponse sur this thread
Merci Jim, Im pas programmeur expert, donc je crains que je ne sais pas exactement ce que vous voulez dire, en particulier la partie sur « inline » J'ai essayé de modifier loadData() (inclus dans un EDIT à la question) mais en vain. Même problème. Je n'ai probablement pas mis en œuvre ce que vous avez suggéré. Toute autre aide grandement appréciée.Merci – FauxReal
Mes excuses pour le jargon, «inlining» signifie copier le code d'une méthode à l'endroit où elle est appelée et supprimer la méthode. Vous pouvez le faire vous-même ou automatiquement dans Eclipse avec le menu Refactor. Quoi qu'il en soit, l'essentiel de ma suggestion originale était que la bonne façon de configurer les contrôles où une opération longue est impliquée est 1. l'installation initiale, qui établit un nouveau thread pour 2. obtenir les données, qui quand elle est complète, runOnUiThread() avec 3. remplir les contrôles avec les données. –
Merci encore Jim, J'ai changé la méthode onCreate comme vous l'avez suggéré (je pense). Vous pouvez le voir ci-dessus dans la 2ème fenêtre de code. Le runOnUiThread devait-il aller dans le Thread()? Cela ne fonctionne toujours pas. Lorsque je débogue, il semble configurer l'ensemble de l'interface utilisateur avant même qu'il ne commence à exécuter le (s) thread (s). – FauxReal