3

有一些问题已经接近这个问题,但它们对我没有太大帮助。所以来了一个新的。

我有一个有两个选项卡的活动。每个选项卡都包含一个 ListFragment(确切地说是 SherlockListFragment)。一个选项卡显示购物清单对象列表,另一个选项卡显示食谱对象列表。现在我想创建一个 DialogFragment 来重命名列表或配方或我以后可能添加到应用程序中的任何其他对象。

此处提供的解决方案听起来很有希望,但由于无法注册 ListFragment 来监听对话框中的点击,我应该让我的 Activity 来监听它们,这并不理想,因为这样我的 Fragment 就不是独立的了。 如何从通用对话框类中获取数据

理想情况下,我希望我的重命名对话框尽可能独立且可重用。到目前为止,我只发明了一种方法来做到这一点。将对象 className 和 id 发送到对话框,然后使用 switch case 从数据库中获取正确的对象。这样,对话框将能够自行更新对象名称(如果对象具有重命名方法)。但是对数据库的重新查询听起来只是转储,因为 ListFragment 已经拥有该对象。然后对话框需要在开关中为每种新类型的对象添加一个新案例。

有任何想法吗?

4

2 回答 2

2

实际上,我只是创建了与您所询问的内容类似的对话片段。我是为一个相当大的应用程序而设计的,我们的主要活动扩展的对话侦听器的数量只是为了侦听单个对话的结果,这有点荒谬。

为了让事情变得更灵活,我转而使用 Google 的 Guava 并发库中的 ListenableFuture。

我创建了以下要使用的抽象类:

public abstract class ListenableDialogFragment<T> extends DialogFragment implements ListenableFuture<T> {

private SettableFuture<T> _settableFuture;

public ListenableDialogFragment() {
    _settableFuture = SettableFuture.create();
}

@Override
public void addListener(Runnable runnable, Executor executor) {
    _settableFuture.addListener(runnable, executor);
}

@Override
public boolean cancel(boolean mayInterruptIfRunning) {
    return _settableFuture.cancel(mayInterruptIfRunning);
}

@Override
public boolean isCancelled() {
    return _settableFuture.isCancelled();
}

@Override
public boolean isDone() {
    return _settableFuture.isDone();
}

@Override
public T get() throws InterruptedException, ExecutionException {
    return _settableFuture.get();
}

@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
    return _settableFuture.get(timeout, unit);
}

public void set(T value) {
    _settableFuture.set(value);
}

public void setException(Throwable throwable) {
    _settableFuture.setException(throwable);
}

// Resets the Future so that it can be provided to another call back
public void reset() {
    _settableFuture = SettableFuture.create();
}

@Override
public void onDismiss(DialogInterface dialog) {
    // Cancel the future here in case the user cancels our of the dialog
    cancel(true);
    super.onDismiss(dialog);
}

使用这个类,我可以创建自己的自定义对话框片段并像这样使用它们:

            ListenableDialogFragment<int> dialog = GetIdDialog.newInstance(provider.getIds());

    Futures.addCallback(dialog, new FutureCallback<int>() {
        @Override
        public void onSuccess(int id) {
            processId(id);
        }

        @Override
        public void onFailure(Throwable throwable) {
            if (throwable instanceof CancellationException) {
                // Task was cancelled
            }

            processException(throwable);
        }
    });

这就是 GetIdDialog 是 ListenableDialogFragment 的自定义实例的地方。如果需要,我可以通过简单地在 onSuccess 和 onFailure 方法中调用 dialog.reset 来重用同一个对话框实例,以确保重新加载内部 Future 以添加回回调。

我希望这能够帮到你。

编辑:抱歉忘了添加,在您的对话框中,您可以实现一个点击监听器,它会执行以下操作来触发未来:

private class SingleChoiceListener implements DialogInterface.OnClickListener {
    @Override
    public void onClick(DialogInterface dialog, int item) {
        int id = _ids[item];

        // This call will trigger the future to fire
        set(id);
        dismiss();
    }
}
于 2013-06-26T13:28:56.283 回答
1

我可能只是使用一些变化的静态工厂模式来允许 DialogFragment 的动态初始化。

private enum Operation {ADD, EDIT, DELETE}

private String title;
private Operation operation;

public static MyDialogFragment newInstance(String title, Operation operation)
{
    MyDialogFragment dialogFragment = new DialogFragment();
    dialogFragment.title = title;   // Dynamic title
    dialogFragment.operation = operation;

    return dialogFragment;
}

或者..我会更推荐这个,为每种类型的操作都有一个静态工厂方法,你将使用它。这允许不同的动态变化更加具体,并确保一切协同工作。这也允许信息构造函数。

例如。

public static MyDialogFragment newAddItemInstance(String title)
{
    MyDialogFragment dialogFragment = new DialogFragment();
    dialogFragment.title = title;   // Dynamic title

    return dialogFragment;
}

public static MyDialogFragment newEditItemInstance(String title)
{
    MyDialogFragment dialogFragment = new DialogFragment();
    dialogFragment.title = title;   // Dynamic title

    return dialogFragment;
}

然后当然创建一个接口,每个调用 Activity / Fragment (在这种情况下,您需要将此 Fragment 设置为 targetFragment 并在您的 DialogFragment 中获取对该目标 Fragment 的引用)以便在目标 Fragment 中处理实现和与 DialogFragment 无关。

总结:有多种方法可以解决这个问题,为简单起见,我会坚持某种形式的静态工厂模式,并巧妙地使用接口将任何逻辑与 DialogFragment 分离,从而使其更具可重用性

编辑:根据您的评论,我建议您看两件事:

  • 目标片段(请参阅我对您的问题所做的评论)。您可以从 DialogFragment 调用 ListFragment 中的方法。

  • 战略模式。策略模式如何运作?. 这允许您对不同的对象执行相同的操作(每种类型都有各种定制的实现)。非常有用的模式。

于 2013-06-26T14:23:19.960 回答