Android:如何使用接口仅允许访问部分对象成员

时间:2011-07-07 18:03:31

标签: java android

如何“传递界面”,即CommonsWare在question below中向提问者建议的内容?>

  

另一个是制作DownloadFileTask   公开并传递一些东西   构造函数。在这种情况下,要尽量减少   耦合,可能是你没有   想传递一个Activity,但是有些   其他类型的界限限制   AsyncTask可以做什么。这样,   你可以选择实施   一个Activity上的接口,或者作为一个   单独的对象,或其他什么。 -   CommonsWare 2010年4月27日17:44

如何让线程只访问一些(或只是一个)对象公共方法?

答案>请参阅以下答案。

真正的问题是我对界面的误解。如果将方法F的输入类型(或类的参数化)指定为接口[即F(my_interface i)]和一个对象X被传递给实现my_interface [F(X)]的那个方法,那么即使存在其他成员,也只有方法F可以访问实现my_interface的X成员。

我认为接口只在实现类上设置了约束。我不明白,当一个接口被用作一个类型时,它也会限制对实现类成员的访问。回想起来,鉴于Java是静态类型的,这是显而易见的。有关详细信息,请参阅Java tutorial

2 个答案:

答案 0 :(得分:0)

将接口传递给AsyncTask就像使用任何函数一样。例如:

interface MyInterface { ... }

class MyClass implements MyInterface { ... }

AsyncTask<MyInterface, Integer, Void> myAsyncTask = new ...;
myAsyncTask.execute(myClassInstance);

AsyncTask是一个Generic,它允许您指定参数类型,进度返回类型和结果类型(分别为MyInterface,Integer,Void)。您可以指定所需的任何接口,类,枚举或基元类型。

从这里开始,它只是您的标准编码。创建一个扩展接口的类,使用参数设置创建异步任务,传入类,任务只能访问接口函数。你需要小心线程问题(数据竞赛等)。

答案 1 :(得分:0)

假设您需要能够报告某些后台任务的步骤。您可以通过更改标签文本或更改通知气泡的文本来选择执行此操作。

一种方法是将标签或通知传递给后台任务:

public class BackgroundTask {
    private Label labelToUpdate;
    private Notification notificationToUpdate;

    public BackgroundTask(Label label) {
        this.labelToUpdate = label;
    }

    public BackgroundTask(Notification notification) {
        this.notificationToUpdate = notification;
    }

    //...
    private void reportNewStep(String step) {
        if (labelToUpdate != null) {
            labelToUpdate.setText(step);
        }
        if (notificationToUpdate != null) {
            notificationToUpdate.alert(step);
        }
    }
}

这将BackgroundTask与UI相结合,并以两种可能的方式报告进度。如果添加第三个,则必须更改BackGroundTask的代码。

现在提取一个界面:

public interface ProgressListener {
    void report(String step);
}

public class BackgroundTask {
    private ProgressListener listener;

    public BackgroundTask(ProgressListener listener) {
        this.listener = listener;
    }

    //...
    private void reportNewStep(String step) {
        listener.report(step);
    }
}

BackgroundTask现在更简单,并且不再依赖于报告进度的所有可能方式。调用者只需要为它提供ProgressListener接口的实现。对于基于标签的进度,它将执行以下操作:

BackgroundTask task = new BackgroundTask(new ProgressListener() {
    @Override
    public void report(String step) {
        label.setText(step);
    }
});

或者您的活动可以直接实施ProgressListener:

public class MyActivity implements ProgressListener {
    private Notification notification;

    // ...
    @Override
    public void report(String step) {
        notification.alert(step);
    }
    // ...
    BackgroundTask backgroundTask = new BackgroundTask(this);
}

Label和BackgroundTask之间或MyActivity和BackgroundTask之间不再有耦合。 BackgroundTask不再调用Label,Notification或MyActivity的任何方法。它只能调用它应该调用的内容:专用ProgressListener接口的方法。