Android MVP

android

Cześć, dzisiaj pokaże Ci wzorzec na którym możesz opierać swoje androidowe projekty czyli Model View Presenter.


 
 
 
 

Android MVP

 

Co to jest MVP w Androidzie? Wykorzystująć ten wzorzec możemy odseparować od siebie warstwę danych modelu oraz widoku poprzez łącznik jakim jest presenter. W skrócie model dostarcza nam informację (dane), presenter operuje na tych danych i przekazuję je do widoku który może być aktywnością, fragmentem czy też widgetem. Stosująć opisywany wzorzec to nie ma znaczenia bo widok obsługuje interakcję z użytkownikiem oraz wyświetla dane z presentera gdzie zaimplementowana jest logika aplikacji. Ok ktoś pomyśli spoko ziomek to tak samo jak MVC (Model View Controller) no właśnie nie do końca w MVP cała odpowiedzialność spoczywa na presenterze który jest głównym łącznikiem pomiędzy pozostałymi warstwami. Jest też wiele implementacji obu wzorców które mogą się od siebie różnić np MVP ewoluował w VIPER (View Interactor Presenter Entity Router). Główne cechy MVP Jeden prezenter odnosi sie do jednego widoku, dane zawsze muszą przejść przez prezenter, widok nie ma bezposredniego dostepu do modelu, widok odpowiada za obsluge zdarzen uzytkownika i wyświetlanie danych. Stwórzmy sobie bardzo prostą aplikację opartą o najbardziej podstawową implementację wzorca mvp gdzie będziemy wyświetlać, dodawać i usuwać jakieś zadania.

 

Model

 

Rozpocznijmy od zdefiniowania naszego modelu, niech to będzie klasa Task z dwoma polami name i description.

 

public class Task {

    private String name;
    private String description;

    public Task(String name, String description) {

        this.name = name;
        this.description = description;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

 

View

 

Ok na tych danych będziemy operować,  w innych implementacjach możesz spotkać się np z interactorami czyli danymi które zasysamy gdzieś z serwisu w formacie JSON. Ale skupmy się narazie na taskach. Teraz definujemy interejes naszego widoku zastanówmy się co będzie nam potrzebne w naszym widoku. Będziemy musieli jakoś wyświetlić nasze dane, będziemy chcieli jakimś buttonem dodać nowy task a następnie wyczyścić kontrolki odpowiedzialne za dodawanie zadań. Napewno chcielibyśmy usunąć nasze zadanie gdy nie będzie nam potrzebne,

 

public interface ITaskView {

    void loadData();

    void addTask();

    boolean onItemLongClick(int position);

    void clearData();
}

 

Przejdźmy teraz do widoku wykorzystamy tutaj bibliotekę ButterKnife aby trochę czytelniej wyglądał nasz przykład w skrócie zamiast powtarzalnych metod takich jak findViewById() przy inicjalizacji widoków stosujemy adnotację podobnie przy obsłudzie eventów. W metodzie onCreate() inicjalizujemy nasz presenter, a następnie w nadpisanych metodach naszego interjesu wykorzystujemy presenter do dostarczenia odpowiednich danych jak widzisz nigdzie w widoku nie wykorzystujemy naszego modelu wszystko odbywa się przez presenter.

 

public class TaskActivity extends AppCompatActivity implements ITaskView {

    private IPresenterTask presenterTask;

    @BindView(R.id.tasksList)
    ListView tasksList;

    @BindView(R.id.taskName)
    EditText nameOfTask;

    @BindView(R.id.tasksDesc)
    EditText descTask;

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

        ButterKnife.bind(this);
        presenterTask = new PresenterTask(this);
    }

    @Override
    protected void onResume() {
        super.onResume();

        presenterTask.refresh();
    }

    @Override
    public void loadData() {

        tasksList.setAdapter(new CustomAdapter(this, R.layout.custom_list, presenterTask.getAllTasks()));
    }

    @Override
    @OnClick(R.id.addTasks)
    public void addTask() {

        presenterTask.addNewTask(nameOfTask.getText().toString(), descTask.getText().toString());
        presenterTask.refresh();
    }

    @Override
    @OnItemLongClick(R.id.tasksList)
    public boolean onItemLongClick(int position) {

        presenterTask.deleteTask(tasksList.getItemAtPosition(position));
        presenterTask.refresh();

        return true;
    }

    @Override
    public void clearData() {

        nameOfTask.setText("");
        descTask.setText("");
    }
}

 

Presenter

 

Następnie definujemy interfejs presentera czyli naszą logikę zwykle widok i presenter są sobie równe 1:1 czyli potrzebne nam metody analogiczne do tych w widoku dodaj task, usuń, zwróć wszystkie taski, i odśwież widok.

 

public interface IPresenterTask{

    void addNewTask(String name, String descOfTask);
    
    List<Task> getAllTasks();
    
    void deleteTask(Object name);
    
    void refresh();
}

 

Teraz tworzymy implementajce naszego interfejsu. Będziemy tutaj tworzyć listę naszych tasków, tworzymy instancje naszego widoku którą inicjaliuzjemy w konstruktorze, w implementowanych metodach operujemy na liście nic trudnego:) w metodzie refresh ładujemy jeszcze raz dane do widoku.

 

public class PresenterTask implements IPresenterTask {

    private ITaskView view;
    private List<Task> listOfTasks;

    public PresenterTask(ITaskView view) {

        this.view = view;
        listOfTasks = new ArrayList<>();
    }

    @Override
    public void addNewTask(String name, String descOfTask) {

        listOfTasks.add(new Task(name, descOfTask));
        view.clearData();
    }

    @Override
    public List<Task> getAllTasks() {

        return listOfTasks;
    }

    @Override
    public void deleteTask(Object t) {

        Task task = (t instanceof Task) ? (Task) t : null;

        if (task != null)
            listOfTasks.remove(task);
    }

    @Override
    public void refresh() {

        if (view != null)
            view.loadData();
    }
}

 

W naszych aplikacji możemy tworzyć oczywiście więcej niż jeden presenter dzięki czemu nasz kod stanie się bardziej czytelny rozszerzalny i ławtiejszy w testowaniu. Aplikację z tego wpisu udostępniam ci na githubie do przeanalizowania.

Cześć:)

 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *