Уроки для java android

Пишем первое приложение для Android

В любом деле самое сложное — это начало. Часто бывает тяжело войти в контекст, с чем столкнулся и я, решив разработать свое первое Android-приложение. Настоящая статья для тех, кто хочет начать, но не знает с чего.

Статья затронет весь цикл разработки приложения. Вместе мы напишем простенькую игру “Крестики-Нолики” с одним экраном (в ОС Android это называется Activity).

Отсутствие опыта разработки на языке Java не должно стать препятствием в освоении Android. Так, в примерах не будут использоваться специфичные для Java конструкции (или они будет минимизированы на столько, на сколько это возможно). Если Вы пишете, например, на PHP и знакомы с основополагающими принципами в разработке ПО, эта статья будет вам наиболее полезна. В свою очередь так как, я не являюсь экспертом по разработке на Java, можно предположить, что исходный код не претендует на лейбл “лучшие практики разработки на Java”.

Читайте также:  Java thread pool stop thread

Установка необходимых программ и утилит

  1. JDK — набор для разработки на языке Java;
  2. Android SDK and AVD Manager — набор утилит для разработки + эмулятор;
  3. IDE c поддержкой разработки для Android:
    • Eclipse + ADT plugin;
    • IntelliJ IDEA Community Edition;
    • Netbeans + nbandroid plugin;

Утилиты устанавливаются в определенном выше порядке. Ставить все перечисленные IDE смысла нет (разве только если Вы испытываете затруднения с выбором подходящей). Я использую IntelliJ IDEA Community Edition, одну из самых развитых на данный момент IDE для Java.

Запуск виртуального устройства

Запустив AVD Manager и установив дополнительные пакеты (SDK различных версий), можно приступить к созданию виртуального устройства с необходимыми параметрами. Разобраться в интерфейсе не должно составить труда.

Список устройств

Создание проекта

Мне всегда не терпится приступить к работе, минимизируя подготовительные мероприятия, к которым относится создание проекта в IDE, особенно, когда проект учебный и на продакшн не претендует.

По нажатию кнопки F6 проект соберется, откомпилируется и запустится на виртуальном девайсе.

Структура проекта

На предыдущем скриншоте видна структура проекта. Так как в этой статье мы преследуем сугубо практические цели, заострим внимание лишь на тех папках, которые будем использовать в процессе работы. Это следующие каталоги: gen, res и src.

В папке gen находятся файлы, которые генерируются автоматически при сборке проекта. Вручную их менять нельзя.

Папка res предназначена для хранения ресурсов, таких как картинки, тексты (в том числе переводы), значения по-умолчанию, макеты (layouts).

src — это папка в которой будет происходить основная часть работы, ибо тут хранятся файлы с исходными текстами нашей программы.

Первые строки

Как только создается Activity (экран приложения), вызывается метод onCreate(). IDE заполнила его 2 строчками:

super.onCreate(savedInstanceState); setContentView(R.layout.main); 

Метод setContentView (равносильно this.setContentView) устанавливает xml-макет для текущего экрана. Далее xml-макеты будем называть «layout», а экраны — «Activity». Layout в приложении будет следующий:

Для этого приложения идеально подойдет TableLayout. Id можно присвоить любому ресурсу. В данном случае, TableLayout присвоен При помощи метода findViewById() можно получить доступ к виду:

 private TableLayout layout; // это свойство класса KrestikinolikiActivity public void onCreate(Bundle savedInstanceState)

Теперь необходимо реализовать метод buildGameField(). Для этого требуется сгенерировать поле в виде матрицы. Этим будет заниматься класс Game. Сначала нужно создать класс Square для ячеек и класс Player, объекты которого будут заполнять эти ячейки.

Square.java

package com.example; public class Square < private Player player = null; public void fill(Player player) < this.player = player; >public boolean isFilled() < if (player != null) < return true; >return false; > public Player getPlayer() < return player; >> 

Player.java

package com.example; public class Player < private String name; public Player(String name) < this.name = name; >public CharSequence getName() < return (CharSequence) name; >> 

Все классы нашего приложения находятся в папке src.

Game.java

package com.example; public class Game < /** * поле */ private Square[][] field; /** * Конструктор * */ public Game() < field = new Square[3][3]; squareCount = 0; // заполнение поля for (int i = 0, l = field.length; i < l; i++) < for (int j = 0, l2 = field[i].length; j < l2; j++) < field[i][j] = new Square(); squareCount++; >> > public Square[][] getField() < return field; >> 

Инициализация Game в конструкторе KrestikinolikiActivity.

public KrestikinolikiActivity() < game = new Game(); game.start(); // будет реализован позже >

Метод buildGameField() класса KrestikinolikiActivity. Он динамически добавляет строки и колонки в таблицу (игровое поле):

private Button[][] buttons = new Button[3][3]; //(. ) private void buildGameField() < Square[][] field = game.getField(); for (int i = 0, lenI = field.length; i < lenI; i++ ) < TableRow row = new TableRow(this); // создание строки таблицы for (int j = 0, lenJ = field[i].length; j < lenJ; j++) < Button button = new Button(this); buttons[i][j] = button; button.setOnClickListener(new Listener(i, j)); // установка слушателя, реагирующего на клик по кнопке row.addView(button, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); // добавление кнопки в строку таблицы button.setWidth(107); button.setHeight(107); >layout.addView(row, new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.WRAP_CONTENT)); // добавление строки в таблицу > > 

В строке 8 создается объект, реализующий интерфейс View.OnClickListener. Создадим вложенный класс Listener. Он будет виден только из KrestikinolikiActivity.

public class Listener implements View.OnClickListener < private int x = 0; private int y = 0; public Listener(int x, int y) < this.x = x; this.y = y; >public void onClick(View view) < Button button = (Button) view; >> 
public class Game < /** * игроки */ private Player[] players; /** * поле */ private Square[][] field; /** * начата ли игра? */ private boolean started; /** * текущий игрок */ private Player activePlayer; /** * Считает колличество заполненных ячеек */ private int filled; /** * Всего ячеек */ private int squareCount; /** * Конструктор * */ public Game() < field = new Square[3][3]; squareCount = 0; // заполнение поля for (int i = 0, l = field.length; i < l; i++) < for (int j = 0, l2 = field[i].length; j < l2; j++) < field[i][j] = new Square(); squareCount++; >> players = new Player[2]; started = false; activePlayer = null; filled = 0; > public void start() < resetPlayers(); started = true; >private void resetPlayers() < players[0] = new Player("X"); players[1] = new Player("O"); setCurrentActivePlayer(players[0]); >public Square[][] getField() < return field; >private void setCurrentActivePlayer(Player player) < activePlayer = player; >public boolean makeTurn(int x, int y) < if (field[x][y].isFilled()) < return false; >field[x][y].fill(getCurrentActivePlayer()); filled++; switchPlayers(); return true; > private void switchPlayers() < activePlayer = (activePlayer == players[0]) ? players[1] : players[0]; >public Player getCurrentActivePlayer() < return activePlayer; >public boolean isFieldFilled() < return squareCount == filled; >public void reset() < resetField(); resetPlayers(); >private void resetField() < for (int i = 0, l = field.length; i < l; i++) < for (int j = 0, l2 = field[i].length; j < l2; j++) < field[i][j].fill(null); >> filled = 0; > > 

Определение победителя

К. О. подсказывает, что в крестики-нолики выирывает тот, кто выстроет X или O в линию длиной, равной длине поля по-вертикали, или по-горизонтали, или по-диагонали. Первая мысль, которая приходит в голову — это написать методы для каждого случая. Думаю, в этом случае хорошо подойдет паттерн Chain of Responsobility. Определим интерфейс

package com.example; public interface WinnerCheckerInterface

Так как Game наделен обязанностью выявлять победителя, он реализует этот интерфейс. Настало время создать виртуальных «лайнсменов», каждый из которых будет проверять свою сторону. Все они реализует интерфейс WinnerCheckerInterface.

WinnerCheckerHorizontal.java

package com.example; public class WinnerCheckerHorizontal implements WinnerCheckerInterface < private Game game; public WinnerCheckerHorizontal(Game game) < this.game = game; >public Player checkWinner() < Square[][] field = game.getField(); Player currPlayer; Player lastPlayer = null; for (int i = 0, len = field.length; i < len; i++) < lastPlayer = null; int successCounter = 1; for (int j = 0, len2 = field[i].length; j < len2; j++) < currPlayer = field[i][j].getPlayer(); if (currPlayer == lastPlayer && (currPlayer != null && lastPlayer !=null)) < successCounter++; if (successCounter == len2) < return currPlayer; >> lastPlayer = currPlayer; > > return null; > > 

WinnerCheckerVertical.java

package com.example; public class WinnerCheckerVertical implements WinnerCheckerInterface < private Game game; public WinnerCheckerVertical (Game game) < this.game = game; >public Player checkWinner() < Square[][] field = game.getField(); Player currPlayer; Player lastPlayer = null; for (int i = 0, len = field.length; i < len; i++) < lastPlayer = null; int successCounter = 1; for (int j = 0, len2 = field[i].length; j < len2; j++) < currPlayer = field[j][i].getPlayer(); if (currPlayer == lastPlayer && (currPlayer != null && lastPlayer !=null)) < successCounter++; if (successCounter == len2) < return currPlayer; >> lastPlayer = currPlayer; > > return null; > > 

WinnerCheckerDiagonalLeft.java

package com.example; public class WinnerCheckerDiagonalLeft implements WinnerCheckerInterface < private Game game; public WinnerCheckerDiagonalLeft(Game game) < this.game = game; >public Player checkWinner() < Square[][] field = game.getField(); Player currPlayer; Player lastPlayer = null; int successCounter = 1; for (int i = 0, len = field.length; i < len; i++) < currPlayer = field[i][i].getPlayer(); if (currPlayer != null) < if (lastPlayer == currPlayer) < successCounter++; if (successCounter == len) < return currPlayer; >> > lastPlayer = currPlayer; > return null; > > 

WinnerCheckerDiagonalRight.java

package com.example; public class WinnerCheckerDiagonalRight implements WinnerCheckerInterface < private Game game; public WinnerCheckerDiagonalRight(Game game) < this.game = game; >public Player checkWinner() < Square[][] field = game.getField(); Player currPlayer; Player lastPlayer = null; int successCounter = 1; for (int i = 0, len = field.length; i < len; i++) < currPlayer = field[i][len - (i + 1)].getPlayer(); if (currPlayer != null) < if (lastPlayer == currPlayer) < successCounter++; if (successCounter == len) < return currPlayer; >> > lastPlayer = currPlayer; > return null; > > 
//(. ) /** * "Судьи" =). После каждого хода они будут проверять, * нет ли победителя */ private WinnerCheckerInterface[] winnerCheckers; //(. ) public Game() < //(. ) winnerCheckers = new WinnerCheckerInterface[4]; winnerCheckers[0] = new WinnerCheckerHorizontal(this); winnerCheckers[1] = new WinnerCheckerVertical(this); winnerCheckers[2] = new WinnerCheckerDiagonalLeft(this); winnerCheckers[3] = new WinnerCheckerDiagonalRight(this); //(. ) >
public Player checkWinner() < for (WinnerCheckerInterface winChecker : winnerCheckers) < Player winner = winChecker.checkWinner(); if (winner != null) < return winner; >> return null; > 
public void onClick(View view) < Button button = (Button) view; Game g = game; Player player = g.getCurrentActivePlayer(); if (makeTurn(x, y)) < button.setText(player.getName()); >Player winner = g.checkWinner(); if (winner != null) < gameOver(winner); >if (g.isFieldFilled()) < // в случае, если поле заполнено gameOver(); >> 
private void gameOver(Player player) < CharSequence text = "Player \"" + player.getName() + "\" won!"; Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); game.reset(); refresh(); >private void gameOver()

Для Java, gameOver(Player player) и gameOver() — разные методы. Воспользовавшись Builder’ом Toast.makeText, можно быстро создать и показать уведомление. refresh() обновляет состояние поля:

private void refresh() < Square[][] field = game.getField(); for (int i = 0, len = field.length; i < len; i++) < for (int j = 0, len2 = field[i].length; j < len2; j++) < if (field[i][j].getPlayer() == null) < buttons[i][j].setText(""); >else < buttons[i][j].setText(field[i][j].getPlayer().getName()); >> > > 

Готово! Надеюсь, эта статья помогла Вам освоиться в мире разработки под OS Android. Благодарю за внимание!

Видео готового приложения

PS: статья была опубликована по просьбе комментаторов этого поста.

Источник

Уроки

Это урок-введение. Здесь мы пока ничего кодить не будем, я распишу причины, которые побудили меня создать этот сайт.

Урок 2. Установка Android Studio

Для того, чтобы писать программы — нужна среда разработки. В этом уроке мы подробно рассмотрим, как установить и настроить эту среду разработки.

Я буду описывать установку применимо к операционной системе Windows 7.

Урок 3. Создание AVD. Первое приложение. Структура Android-проекта.

Для того, чтобы тестировать приложения, нам понадобится Android Virtual Device (AVD). Это эмулятор Android-смартфона, на который мы сможем устанавливать созданные нами приложения, и запускать их там. Давайте его создадим.

Урок 4. Компоненты экрана и их свойства

Давайте посмотрим, как в Андроид приложениях формируется то, что мы видим на экране.

Урок 5. Layout-файл в Activity. XML представление. Смена ориентации экрана.

На прошлом уроке мы выяснили, что Activity читает layout-файл и отображает то, что в нем сконфигурировано. Теперь выясним, откуда Activity знает, какой именно layout-файл читать.

Урок 6. Виды Layouts. Ключевые отличия и свойства.

Расположение View-элементов на экране зависит от ViewGroup (Layout), в которой они находятся. В этом уроке мы рассмотрим основные виды Layout.

LinearLayout – отображает View-элементы в виде одной строки (если он Horizontal) или одного столбца (если он Vertical). Я использовал это на прошлом уроке, когда демонстрировал использование layout-файлов при смене ориентации.

TableLayout – отображает элементы в виде таблицы, по строкам и столбцам.

RelativeLayout – для каждого элемента настраивается его положение относительно других элементов.

AbsoluteLayout – для каждого элемента указывается явная позиция на экране в системе координат (x,y)

Урок 7. Layout параметры для View-элементов.

— разбираемся в характеристиках экрана
— рассматриваем layout параметры (высота, ширина, отступ, гравитация, вес)

Урок 8. Работаем с элементами экрана из кода

— научимся обращаться из кода к View-элементам на экране и менять их свойства

Урок 9. Обработчики событий на примере Button.

— научимся обрабатывать нажатие кнопки и узнаем, что такое обработчик

Урок 10. Оптимизируем реализацию обработчиков.

— научимся использовать один обработчик для нескольких View-элементов
— научим Activity выступать в качестве обработчика

Урок 11. Папка res/values. Используем ресурсы приложения.

— узнаем, зачем нужна папка res/values, что в ней можно хранить и как использовать

Урок 12. Логи и всплывающие сообщения

— рассмотрим логи приложения и всплывающие сообщения

Источник

Оцените статью