Zum Hauptinhalt springen

Flutter PHP MySQL – Fill ListView mit Bildern und Text

Flutter ist ein Framework für die Erstellung von mobilen Apps, sowohl für Android als auch für iOS. Tatsächlich können Sie es sogar für die Erstellung von Web- und Desktop-Apps verwenden. Es ist ein ausgereiftes und gut unterstütztes Framework und liegt derzeit im Trend.

MySQL hingegen ist eine Datenbank, die hauptsächlich zum Hosten von Daten für Web- und mobile Anwendungen verwendet wird. Es ist kostenlos und ist wahrscheinlich das beliebteste RDBMS-Framework auf dem Markt. Im Allgemeinen verwenden wir es gerne in Verbindung mit PHP, einer serverseitigen Programmiersprache. PHP und MySQL sind eine Kombination, die den größten Teil des Internets versorgt.

In dieser Lektion wollen wir sehen, wie man sowohl mit der MySQL-Datenbank als auch mit der Flutter-Anwendung arbeiten kann. Wir führen einfach einen HTTP GET gegen den PHP MySQL Server durch, laden Daten herunter und füllen unsere benutzerdefinierte Listenansicht mit Bildern und Text. Wenn dann eine einzelne Karte in unserer Listenansicht angeklickt wird, öffnen wir eine Detailseite und geben die Daten ein, die wir von MySQL heruntergeladen haben.

Demo

Hier ist die Demo dessen, was im Projekt erstellt wird.

Video-Tutorial

Hier ist das Video-Tutorial:

1. PHP

Zuerst müssen wir PHP-Code schreiben, der:

  1. Verbindung zur mysql-Datenbank mit der Klasse mysqli.
  2. Alle Datensätze aus unserer mysql-Datenbanktabelle auswählen.
  3. Rückgabe der Ergebnisse an ein PHP-Array.
  4. JSON-Kodierung dieses Arrays und Ausgabe an den Aufrufer.
(a). index.php

Dies ist die einzige Datei, die wir haben. Wir schreiben objektorientierten PHP-Code. Der erste Schritt in dieser Datei besteht darin, eine Klasse Constants zu erstellen, die unsere Datenbank-Zugangsdaten enthalten wird. Denken Sie daran, dass wir unsere Datenbank in MySQL hosten, also müssen wir Zugangsdaten wie den Datenbanknamen, den Benutzernamen und das Passwort festlegen.

In der Datei index.php schreiben wir den ersten PHP-Tag:

<?php

Dann erstellen wir die Klasse mit statischen Datenbankanmeldeinformationen:

class Constants
{
//DATABASE DETAILS
static $DB_SERVER="localhost";
static $DB_NAME="spacecraftsDB";
static $USERNAME="root";
static $PASSWORD="";

Dann definieren wir die Sql-Anweisung für die Auswahl aller Daten aus der Datenbank:

    static $SQL_SELECT_ALL="SELECT * FROM spacecraftsTB";

}

In der gleichen php-Datei erstellen Sie eine weitere Klasse, die unsere CRUD-Methoden beherbergen wird:

class Spacecrafts
{

In dieser Klasse werden wir eine Funktion definieren, die eine Verbindung zu unserer Datenbank mit mysqli herstellt. Wir übergeben den Datenbankserver, den Datenbanknamen, den Benutzernamen und das Passwort an den Konstruktor unserer mysqli-Klasse. Wenn die Verbindung fehlerhaft ist, geben wir null zurück, ansonsten geben wir unsere mysqli-Instanz zurück:

    public function connect()
{
$con=new mysqli(Constants::$DB_SERVER,Constants::$USERNAME,Constants::$PASSWORD,Constants::$DB_NAME);
if($con->connect_error)
{
// echo "Unable To Connect"; - For debug
return null;
}else
{
//echo "Connected"; - For debug
return $con;
}
}

Die nächste Funktion wird uns erlauben, Daten aus unserer mysql-Datenbank auszuwählen. Wir werden Daten aus der Datenbank abrufen, dann diese Daten in ein Array schieben, dann dieses Array kodieren und drucken:

    public function select()
{
$con=$this->connect();
if($con != null)
{
$result=$con->query(Constants::$SQL_SELECT_ALL);
if($result->num_rows>0)
{
$spacecrafts=array();
while($row=$result->fetch_array())
{
array_push($spacecrafts, array("id"=>$row['id'],"name"=>$row['name'],
"propellant"=>$row['propellant'],"destination"=>$row['destination'],
"image_url"=>$row['image_url'],"technology_exists"=>$row['technology_exists']));
}
print(json_encode(array_reverse($spacecrafts)));
}else
{
print(json_encode(array("PHP EXCEPTION : CAN'T RETRIEVE FROM MYSQL. ")));
}
$con->close();

}else{
print(json_encode(array("PHP EXCEPTION : CAN'T CONNECT TO MYSQL. NULL CONNECTION.")));
}
}

Hier ist der vollständige Code von index.php:

<?php

class Constants
{
//DATABASE DETAILS
static $DB_SERVER="localhost";
static $DB_NAME="spacecraftsDB";
static $USERNAME="root";
static $PASSWORD="";

//STATEMENTS
static $SQL_SELECT_ALL="SELECT * FROM spacecraftsTB";

}

class Spacecrafts
{
/*******************************************************************************************************************************************/
/*
1.CONNECT TO DATABASE.
2. RETURN CONNECTION OBJECT
*/
public function connect()
{
$con=new mysqli(Constants::$DB_SERVER,Constants::$USERNAME,Constants::$PASSWORD,Constants::$DB_NAME);
if($con->connect_error)
{
// echo "Unable To Connect"; - For debug
return null;
}else
{
//echo "Connected"; - For debug
return $con;
}
}
/*******************************************************************************************************************************************/
/*
1.SELECT FROM DATABASE.
*/
public function select()
{
$con=$this->connect();
if($con != null)
{
$result=$con->query(Constants::$SQL_SELECT_ALL);
if($result->num_rows>0)
{
$spacecrafts=array();
while($row=$result->fetch_array())
{
array_push($spacecrafts, array("id"=>$row['id'],"name"=>$row['name'],
"propellant"=>$row['propellant'],"destination"=>$row['destination'],
"image_url"=>$row['image_url'],"technology_exists"=>$row['technology_exists']));
}
print(json_encode(array_reverse($spacecrafts)));
}else
{
print(json_encode(array("PHP EXCEPTION : CAN'T RETRIEVE FROM MYSQL. ")));
}
$con->close();

}else{
print(json_encode(array("PHP EXCEPTION : CAN'T CONNECT TO MYSQL. NULL CONNECTION.")));
}
}
}
$spacecrafts=new Spacecrafts();
$spacecrafts->select();

//end

2. Dart

Der nächste Teil besteht darin, unseren Dart-Code zu schreiben. Dart ist die Programmiersprache, die wir verwenden, um unsere Flutter-App zu erstellen. Wir haben nur eine Datei:

(a). main.dart

Beginnen Sie mit dem Hinzufügen von Importen:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:http/http.dart' show get;
import 'dart:convert';

Erstellen Sie eine Klasse namens Spacecraft, um ein Raumschiff darzustellen. Dies ist unsere Modellklasse. Wir definieren die Eigenschaften des Raumschiffs als Instanzen dieser Klasse. Zu diesen Eigenschaften gehören id, name, image URL und propellant.

class Spacecraft {
final String id;
final String name, imageUrl, propellant;

Diese Eigenschaften werden über den Konstruktor empfangen:

  Spacecraft({
this.id,
this.name,
this.imageUrl,
this.propellant,
});

Wir werden eine Funktion haben, die für die Umwandlung von JSON-Daten in unser Spacecraft-Objekt verantwortlich ist:

  factory Spacecraft.fromJson(Map<String, dynamic> jsonData) {
return Spacecraft(
id: jsonData['id'],
name: jsonData['name'],
propellant: jsonData['propellant'],
imageUrl: "http://192.168.12.2/PHP/spacecrafts/images/"+jsonData['image_url'],
);
}
}

Wir werden auch einen Bildschirm erstellen müssen, der unsere Daten auflistet. Wir listen unsere Daten in einer ListView auf. Also müssen wir ein ListView-Element erstellen. Wenn dieses ListView-Element angeklickt wird, öffnen wir die Detailseite und zeigen die Ergebnisse in einem anderen Bildschirm an:

  Widget createViewItem(Spacecraft spacecraft, BuildContext context) {
return new ListTile(
title: new Card(
elevation: 5.0,
child: new Container(
decoration: BoxDecoration(border: Border.all(color: Colors.orange)),
padding: EdgeInsets.all(20.0),
margin: EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
Padding(
child: Image.network(spacecraft.imageUrl),
padding: EdgeInsets.only(bottom: 8.0),
),
Row(children: <Widget>[
Padding(
child: Text(
spacecraft.name,
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.right,
),
padding: EdgeInsets.all(1.0)),
Text(" | "),
Padding(
child: Text(
spacecraft.propellant,
style: new TextStyle(fontStyle: FontStyle.italic),
textAlign: TextAlign.right,
),
padding: EdgeInsets.all(1.0)),
]),
],
),
),
),
onTap: () {
//We start by creating a Page Route.
//A MaterialPageRoute is a modal route that replaces the entire
//screen with a platform-adaptive transition.
var route = new MaterialPageRoute(
builder: (BuildContext context) =>
new SecondScreen(value: spacecraft),
);
//A Navigator is a widget that manages a set of child widgets with
//stack discipline.It allows us navigate pages.
Navigator.of(context).push(route);
});
}
}

Vielleicht interessiert es Sie, wie wir die JSON-Daten vom Server herunterladen. Der erste Schritt besteht darin, eine Funktion zu definieren, die ein Future-Objekt zurückgibt. Diese Methode wird eine async sein, damit wir unsere Benutzeroberfläche Thread nicht blockieren. Der generische Parameter dieser Funktion wird eine Liste von Raumschiffen sein:

Future<List<Spacecraft>> downloadJSON() async {

Dann definieren Sie einen JSON-Endpunkt. Dies ist die URL, gegen die wir eine HTTP GET-Anfrage durchführen werden. Dann führen Sie diesen Endpunkt mit der Funktion get() aus:

  final jsonEndpoint =
"http://192.168.12.2/PHP/spacecrafts";

final response = await get(jsonEndpoint);

Wir werden auch den Antwortcode überprüfen, ob wir erfolgreich waren. Ein Antwortstatuscode von 200 bedeutet, dass wir erfolgreich mit dem Server kommuniziert haben. Wir dekodieren also den JSON-Antwortkörper in eine Liste. Diese Liste werden wir in unserer Listenansicht darstellen:

  if (response.statusCode == 200) {
List spacecrafts = json.decode(response.body);
return spacecrafts
.map((spacecraft) => new Spacecraft.fromJson(spacecraft))
.toList();
} else
throw Exception('We were not able to successfully download the json data.');
}

Hier ist der vollständige Code:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:http/http.dart' show get;
import 'dart:convert';

class Spacecraft {
final String id;
final String name, imageUrl, propellant;

Spacecraft({
this.id,
this.name,
this.imageUrl,
this.propellant,
});

factory Spacecraft.fromJson(Map<String, dynamic> jsonData) {
return Spacecraft(
id: jsonData['id'],
name: jsonData['name'],
propellant: jsonData['propellant'],
imageUrl: "http://192.168.12.2/PHP/spacecrafts/images/"+jsonData['image_url'],
);
}
}

class CustomListView extends StatelessWidget {
final List<Spacecraft> spacecrafts;

CustomListView(this.spacecrafts);

Widget build(context) {
return ListView.builder(
itemCount: spacecrafts.length,
itemBuilder: (context, int currentIndex) {
return createViewItem(spacecrafts[currentIndex], context);
},
);
}

Widget createViewItem(Spacecraft spacecraft, BuildContext context) {
return new ListTile(
title: new Card(
elevation: 5.0,
child: new Container(
decoration: BoxDecoration(border: Border.all(color: Colors.orange)),
padding: EdgeInsets.all(20.0),
margin: EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
Padding(
child: Image.network(spacecraft.imageUrl),
padding: EdgeInsets.only(bottom: 8.0),
),
Row(children: <Widget>[
Padding(
child: Text(
spacecraft.name,
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.right,
),
padding: EdgeInsets.all(1.0)),
Text(" | "),
Padding(
child: Text(
spacecraft.propellant,
style: new TextStyle(fontStyle: FontStyle.italic),
textAlign: TextAlign.right,
),
padding: EdgeInsets.all(1.0)),
]),
],
),
),
),
onTap: () {
//We start by creating a Page Route.
//A MaterialPageRoute is a modal route that replaces the entire
//screen with a platform-adaptive transition.
var route = new MaterialPageRoute(
builder: (BuildContext context) =>
new SecondScreen(value: spacecraft),
);
//A Navigator is a widget that manages a set of child widgets with
//stack discipline.It allows us navigate pages.
Navigator.of(context).push(route);
});
}
}

//Future is n object representing a delayed computation.
Future<List<Spacecraft>> downloadJSON() async {
final jsonEndpoint =
"http://192.168.12.2/PHP/spacecrafts";

final response = await get(jsonEndpoint);

if (response.statusCode == 200) {
List spacecrafts = json.decode(response.body);
return spacecrafts
.map((spacecraft) => new Spacecraft.fromJson(spacecraft))
.toList();
} else
throw Exception('We were not able to successfully download the json data.');
}

class SecondScreen extends StatefulWidget {
final Spacecraft value;

SecondScreen({Key key, this.value}) : super(key: key);


_SecondScreenState createState() => _SecondScreenState();
}

class _SecondScreenState extends State<SecondScreen> {

Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('Detail Page')),
body: new Container(
child: new Center(
child: Column(
children: <Widget>[
Padding(
child: new Text(
'SPACECRAFT DETAILS',
style: new TextStyle(fontWeight: FontWeight.bold,fontSize: 20.0),
textAlign: TextAlign.center,
),
padding: EdgeInsets.only(bottom: 20.0),
),
Padding(
//`widget` is the current configuration. A State object's configuration
//is the corresponding StatefulWidget instance.
child: Image.network('${widget.value.imageUrl}'),
padding: EdgeInsets.all(12.0),
),
Padding(
child: new Text(
'NAME : ${widget.value.name}',
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
padding: EdgeInsets.all(20.0),
),
Padding(
child: new Text(
'PROPELLANT : ${widget.value.propellant}',
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
padding: EdgeInsets.all(20.0),
)
], ),
),
),
);
}
}

class MyApp extends StatelessWidget {

Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.deepOrange,
),
home: new Scaffold(
appBar: new AppBar(title: const Text('MySQL Images Text')),
body: new Center(
//FutureBuilder is a widget that builds itself based on the latest snapshot
// of interaction with a Future.
child: new FutureBuilder<List<Spacecraft>>(
future: downloadJSON(),
//we pass a BuildContext and an AsyncSnapshot object which is an
//Immutable representation of the most recent interaction with
//an asynchronous computation.
builder: (context, snapshot) {
if (snapshot.hasData) {
List<Spacecraft> spacecrafts = snapshot.data;
return new CustomListView(spacecrafts);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
//return a circular progress indicator.
return new CircularProgressIndicator();
},
),

),
),
);
}
}

void main() {
runApp(MyApp());
}
//end

Download.

Hier sind die Referenzressourcen:

---