2016-07-04 5 views
2

Ich habe meine benutzerdefinierte Dialogfeld Builder in meiner App, die von vielen Ereignissen auslösen wird: Asynctasks, Web-Service-Nachrichten, UI-Eingabefehler oder von Diensten, die keinen Aktivitätskontext haben . Ich habe immer eine Aktivität namens currentActivity in meiner Application-Klasse erstellt. dann auf Wiederaufnahme von jeder Aktivitäten ihre sitzen auf currentActivity.Was ist die beste Praxis von Global Dialog in meiner Anwendung

@Override 
    protected void onResume() { 
     super.onResume(); 
     MyApplication.currentActivity = MainActivity.this; 

Dann habe ich im Falle der Erstellung von Dialogen diesen Kontext verwendet. aber ich hatte ein Problem. zum Beispiel habe ich RegisterActivity geöffnet und dann currentActivity geändert. Wenn die App dann zum Hintergrund oder zu einem anderen Fall kommt, in dem sich eine andere Aktivität geöffnet hat, stürzt meine App beim Erstellen eines Dialogs mit diesem Kontext ab. so Handhabung Hexe Aktivität ist currentActivity ist ein Kopfschmerz. Ich habe gegoogelt und festgestellt, dass einige Leute den CustomDialog in eine Nicht-Layout-Aktivität einbetten und dann diese Aktivität öffnen. aber es scheint keine gute Lösung zu sein.

AKTUALISIERT

zum Beispiel habe ich eine SMSManager Klasse, die meine ganze Senden von SMS behandeln. Ich möchte den Dialog öffnen, damit der Benutzer einige benutzerdefinierte Optionen auswählt, bevor er SMS sendet.

Was ist also die beste Praxis von Global Dialog in meiner gesamten Anwendung?

Antwort

4

Zunächst einmal - es ist eine sehr schlechte Praxis Verweise auf zu retten Aktivitäten (oder Context im Allgemeinen). Android bietet Ihnen immer einen Verweis auf ein Context Objekt, das Sie zum Erstellen Ihres Dialogs verwenden können. In einem Activity ist es das Objekt selbst (this), in einem Fragment Sie die Context von getActivity() oder getContext() zugreifen können, in einem View-getContext().

Wenn Sie einen Dialog aus Ihrer benutzerdefinierten Klasse anzeigen müssen und keine Referenz auf die Context haben, stellen Sie sicher, dass Sie die Context Referenz für Ihre Klasse mit den oben beschriebenen Methoden angeben.

Versuchen Sie nicht, Dialoge von einem Service anzuzeigen - stellen Sie sicher, dass Ihre App im Vordergrund und sichtbar ist, bevor Sie irgendwelche Dialoge anzeigen. Sie können einen Ereignisbus (oder LocalBroadcastManager) verwenden, um den Status (Fehler, Nachricht oder was auch immer) an Ihre aktuell sichtbaren Activity oder Fragment zu senden. Die "gegenwärtig sichtbare Aktivität oder das Fragment" ist in diesem Fall nur die Activity oder Fragment, die auf solche Ereignisse wartet. Starten Sie in onStart() hören und hören Sie in onStop() Methoden Ihrer Activity oder Fragment. Wenn Sie keine laufenden Aktivitäten zum Anzeigen eines Dialogfelds verwenden möchten und nicht auf das nächste Mal warten möchten, wenn der Benutzer Ihre App startet, würde ich anstelle von Dialogen die Verwendung von notifications vorschlagen.

Bei einer Context können Sie Ihren eigenen Dialog erstellen, wohin Sie mit Hilfe eines Helfer Dialog Builder-Klasse wie folgt wollen:

public class DialogBuilder { 
    private String title; 
    private String message; 
    private String primaryButtonTitle; 
    private String secondaryButtonTitle; 
    private Dialog.OnClickListener primaryButtonListener; 
    private Dialog.OnClickListener secondaryButtonListener; 
    private Activity context; 
    private boolean showIcon; 
    private boolean cancellable; 

    public DialogBuilder(Activity context) { 
     this.context = context; 
    } 

    public DialogBuilder setTitle(@StringRes int title) { 
     this.title = context.getString(title); 
     return this; 
    } 

    public DialogBuilder setTitle(String title) { 
     this.title = title; 
     return this; 
    } 

    public DialogBuilder setMessage(@StringRes int message) { 
     this.message = context.getString(message); 
     return this; 
    } 

    public DialogBuilder setMessage(String message) { 
     this.message = message; 
     return this; 
    } 

    public DialogBuilder setShowIcon() { 
     showIcon = true; 
     return this; 
    } 

    public DialogBuilder setPrimaryButton(@StringRes int title, Dialog.OnClickListener listener) { 
     primaryButtonTitle = context.getString(title); 
     primaryButtonListener = listener; 
     return this; 
    } 

    public DialogBuilder setSecondaryButton(@StringRes int title, Dialog.OnClickListener listener) { 
     secondaryButtonTitle = context.getString(title); 
     secondaryButtonListener = listener; 
     return this; 
    } 

    public DialogBuilder setCancellable(boolean cancellable) { 
     this.cancellable = cancellable; 
     return this; 
    } 

    public AlertDialog create() { 
     AlertDialog.Builder builder = new AlertDialog.Builder(context); 
     View dialogView = LayoutInflater.from(context).inflate(R.layout.my_custom_dialog, null);   
     builder.setView(dialogView); 

     // get your custom views here and configure them based on given settings (field values of this class) 

     final AlertDialog dialog = builder.create(); 
     return dialog; 
    } 
} 

Beispiel für die Verwendung (in einem Fragment):

new DialogBuilder(getActivity()) 
    .setTitle(R.string.title) 
    .setMessage(R.string.message) 
    .setPrimaryButton(R.string.ok, new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int which) { 
      // do something 
      dialog.dismiss();   
     } 
    }) 
    .setSecondaryButton(R.string.settings_cancel, new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int which) { 
      // do something 
      dialog.dismiss();   
     } 
    }).create().show(); 
+0

I Ich weiß, dass es schlecht ist, die aktuelle Aktivität beizubehalten, und ich suche nach einer besseren Lösung. Mein benutzerdefinierter Dialog Builder ist sehr ähnlich zu Ihrem, aber der Punkt es Kontext. Wie gesagt, ich möchte den Dialog von vielen Klassen öffnen, von denen einige keinen Aktivitätskontext haben. Zum Beispiel möchte ich einen Dialog aus meiner SMS-Manager-Klasse oder Web-Service-Klasse anzeigen, der mit dem Anwendungskontext arbeitet. daher kann ich den Dialog mit ihrem Kontext nicht öffnen. – Kenji

+0

Ich habe meine Antwort mit dem Hinweis auf Benachrichtigungen – artkoenig

+0

aktualisiert, so dass Sie sagen, dass kein UI-Dialog von Diensten angezeigt wird, senden Sie einfach ein Ereignis und fangen Sie mit Aktivitäten auf. Das klingt gut und passt zur MVC-Architektur. Aber was ist, wenn mein Dienst mit dem Benutzer kommunizieren und etwas eingeben möchte? – Kenji

-1

einen benutzerdefinierten Dialog erstellen Klasse wie folgt:

public class DialogBoardOut extends Dialog { 

private TextView txtBoardOut; 
private RelativeLayout rel_close_boardout; 

public DialogBoardOut(Context mContext) { 
    super(mContext); 
} 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.dialog_boardout); 

} }

Aufruf wie:

DialogBoardOut dialogQrCode = new DialogBoardOut(HomeBaseActivity.this); 
      dialogQrCode.requestWindowFeature(Window.FEATURE_NO_TITLE); 
      // dialogQrCode.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 
      dialogQrCode.show(); 
      dialogQrCode.getWindow().setLayout(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT); 
+0

mein Problem ist, nicht mit benutzerdefiniertem Dialog-Builder. es geht um Kontext – Kenji

+0

Wenn Sie Dialog in Fragment verwenden möchten, dann verwenden Sie getActivity(). getApplicationContext() und in Aktivität senden getApplicationContext() Bitte erläutern Sie, in welchem ​​Zustand Sie keinen Kontext haben .. so werde ich Sie führen –

Verwandte Themen