Mam narzędzie onClickListener, które wyzwala wywołanie sieciowe, więc chciałbym mieć jakiś sposób, aby pokazać użytkownikowi, że komunikacja jest w toku. Problem, na który napotykam, polega na tym, że nie wydaje mi się, aby wywołać ProgressDialog lub zmienić w jakikolwiek sposób interfejs użytkownika, zanim wywołanie zostanie wykonane wewnątrz programu nasłuchującego onClick. Cały kod działa dobrze, ale zmiany interfejsu nie wchodzą w życie dopiero po uruchomieniu całego kodu w onClickListener.Czy onClickListener nie aktualizuje interfejsu użytkownika, dopóki cały kod w nim nie działa w systemie Android?
Zastanawiam się, czy mój problem polega po prostu na tym, że anonimowa wewnętrzna klasa, taka jak onclicklistener, może zaktualizować interfejs tylko pod koniec swojego biegu? A może mój kod jest po prostu zły.
góry dzięki
Poniżej znajduje się kod dla słuchacza onclick:
relayButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
cPanel.throwProgress(NCDTCPRelayActivity.this);
System.out.println(tvSocketConnection.getText().toString());
if (relayStatusArray[relayNumber] == 0)
{
if (cPanel.TurnOnRelay(relayNumber, 1) == false)
{
changeTitleToRed();
}else{
changeTitleToGreen();
}
}
else {
if (cPanel.TurnOffRelay(relayNumber, 1) == false){
changeTitleToRed();
}else{
changeTitleToGreen();
}
}
cPanel.hideProgress(NCDTCPRelayActivity.this);
}
});
Oto kod na throwProgress i hideProgress odpowiednio (są w podklasie aktywności):
public boolean throwProgress(Context mContext) {
System.out.println("INSIDE THROWPROGRESS");
try {
tempDialog = ProgressDialog.show(mContext, "Connecting", "Connecting", true);
}
catch (RuntimeException e) {
return false;
}
return true;
}
public boolean hideProgress(Context mContext) {
System.out.println("OUTSIDE THROWPROGRESS");
tempDialog.hide();
return true;
}
** Edycja Oto nowy kod dla narzędzia onClickListener, w którym umieściłem wersję roboczą:
public void onClick(View v) {
cPanel.throwProgress(NCDTCPRelayActivity.this);
System.out.println(tvSocketConnection.getText().toString());
handler.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
if (relayStatusArray[relayNumber] == 0)
{
if (cPanel.TurnOnRelay(relayNumber, 1) == false)
{
changeTitleToRed();
}else{
changeTitleToGreen();
}
}
else {
if (cPanel.TurnOffRelay(relayNumber, 1) == false){
changeTitleToRed();
}else{
changeTitleToGreen();
}
}
cPanel.hideProgress(NCDTCPRelayActivity.this);
relayStatusArray = cPanel.getBankStatus(1);
updateButtonText();
}
});
}
Cóż, połączenie sieciowe znajduje się na AsyncTask, ale używam metody AsyncTask(). Execute(). Get(), aby wątek ui czekał na odpowiedź, ponieważ cały program jest używany do uzyskania tych poleceń sieciowych do cel i uzyskiwanie odpowiedzi aresponse. To tylko praca, abyśmy nie dostali wyjątku od sieci w głównym wątku. Czy kod przed wywołaniem nie zostanie wykonany przed kodem za nim? – Poodimizer
Nie wywołuj get() w głównym wątku. Zastąp AsyncTask.onPostExecute() i obsłuż tam odpowiedź. – gngr44
@Poodimizer Nie rób tego! Skutecznie pokonujesz cały cel "AsyncTask", przekształcając go w niepotrzebnie rozbudowane * synchroniczne * zadanie! – Santa