AsyncTask în Ţara Fişierelor, Planeta Android

A fost odată ca niciodată un AsyncTask 

Acest AsyncTask trăia în lumea  Android şi se ocupa să informeze userii că aplicaţia pe care ei o rulează necesită un timp mai mare de execuţie.  Această clasă, AsyncTask, pentru că de felul lui e clasă,  ne salvează, pe noi programatorii, de distracţia cu firele de execuţie deoarece prin implementarea sa default rulează în background un thread al cărui rezultat poate fi afişat în cadrul interfeţei grafice. Deci de felul lui este un personaj pozitiv.

Un task asincron (async task)  este definit prin 3  elemente:  ParamsProgress şi Result plus 4 paşi sau metode: onPreExecute, doInBackground, onProgressUpdate, onPostExecute.

Am lămurit partea cu Async Task, urmează fişierele! 🙂

Fişierele sunt la rândul lor des utilizate şi se pot împrietenii cu mai vechiul nostru prieten AsyncTask. Aşadar am gândit o mini-aplicaţie, mini-proiect sau cum vreţi să o numiţi în care am îmbinat AsyncTask cu citire şi scriere de fişiere în memoria internă. Am ales să scriu şi citesc în/din memoria internă.

Să înceapă distracţia! 😉

Workflow-ul “aplicaţiunii” sau firul epic al poveştii: 2 activităţi, 2 layout-uri, iar ca punct de legătură un buton. În prima activitate vom prelua conţinutul dintr-un EditText şi îl vom salva într-un fişier .txt, după care vom trece în ecranul următor unde vom afişa conţinutul fişierului recent creat. Simplu, nu?! (a se citit: “aplicaţie de începători”  😀 ).

Interfaţa grafică?! Artă în xml, nu altceva…

Structura xml a screen-urilor:

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/white"
    android:padding="15dip">
    <TextView android:text="Continut fisier: "
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="@drawable/black"
    android:textSize="17dp"
    android:layout_marginBottom="10dip">
    </TextView>
    <EditText android:id="@+id/eTxtContent"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:inputType="textMultiLine">
    </EditText>
    <LinearLayout android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center_vertical|center_horizontal">
    <Button android:id="@+id/btnAdaugare"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Adaugare continut"
    android:onClick="btnAdaugare_onClick">
    </Button>
    </LinearLayout>
</LinearLayout>

file_content.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical"
  android:background="@drawable/white"
  android:padding="15dip">
  <TextView android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="Textul preluat din fisier este: "
  android:textColor="@drawable/green"
  android:textSize="17dp">
  </TextView>
  <TextView android:id="@+id/txtContentFromFile"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:textColor="@drawable/black"
  android:textSize="17dp">
  </TextView>
</LinearLayout>

Toate bune şi frumoase!Acum urmează partea cea mai “jmecheră”. (“jmecher”=termen tehnic  😀  ) Deci un nou personaj?!
Cin’ să fie?! Cin’ să fie?! Codul Java, evident!

Activity1.java

package org.async.app;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import android.view.View;
import android.widget.EditText;

public class Activity1 extends Activity
{
	EditText eTxtContinut;
	String fileName="fisierulMeu.txt";
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        eTxtContinut=(EditText)findViewById(R.id.eTxtContent);
    }

    public void btnAdaugare_onClick(View v)
    {
    	String continut=eTxtContinut.getText().toString();
    	saveFile(continut,fileName);
    	Intent act2=new Intent(this, Activity2.class);
    	act2.putExtra("filename",fileName);
    	startActivity(act2);
    }

    public void saveFile(String text, String fileName)
    {
        FileOutputStream fos;
		try
		{
			fos = openFileOutput(fileName, Context.MODE_PRIVATE);
			fos.write(text.getBytes());
			fos.close();
		}
		catch (FileNotFoundException e)
		{
			e.printStackTrace();
		}
	    catch (IOException e)
	    {
			e.printStackTrace();
		}
	    catch(Exception e)
	    {
	    	e.printStackTrace();
	    }
    }
}
Activity2.java
package org.async.app;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TextView;

public class Activity2 extends Activity
{
	TextView txtContentFromFile;
	String fileName;
	@Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.file_content);
        if (Activity2.this.getIntent().getExtras() != null)
        {
        	Bundle bundles = this.getIntent().getExtras();
        	fileName=bundles.getString("filename");
        }

        txtContentFromFile=(TextView)findViewById(R.id.txtContentFromFile);
        new CitireFisier().execute();
    }

	public String readFile(String fileName)
    {
	    StringBuilder sb = new StringBuilder();
    	try
    	{
    	    InputStream instream = openFileInput(fileName);
    	    BufferedReader reader = new BufferedReader(new InputStreamReader(instream));

	        String line = null;
	        try
	        {
	            while ((line = reader.readLine()) != null)
	            {
	                sb.append(line + "\n");
	            }
	            return sb.toString();
	        }
	        catch (IOException e)
	        {
	            e.printStackTrace();
	        }
	        finally
	        {
	        	sb.setLength(0);
	            try
	            {
	                instream.close();
	            }
	            catch (IOException e)
	            {
	                e.printStackTrace();
	            }
	        }
    	  }
    	  catch (java.io.FileNotFoundException e)
    	  {
    	  }
          return sb.toString();
    }

   private class CitireFisier extends AsyncTask<String, Integer, String>
   {
	     ProgressDialog progressDialog;

	     protected void onPreExecute()
         {
        	 progressDialog = new ProgressDialog(Activity2.this);
        	 progressDialog.setCancelable(true);
        	 progressDialog.setMessage("Asteptati... Se obtine continutul fisierului");
             progressDialog.show();
         }

         protected String doInBackground(String... urls)
         {
        	 String content = null;
        	 if(fileName!=null)
             {
                content=readFile(fileName);
             }
        	 return content;
         }

         protected void onPostExecute(String result)
         {
        	 if(result!=null && result.length()>0)
        	 {
              	 txtContentFromFile.setText(result);
        		 progressDialog.dismiss();
        	 }
         }
   }
}

Ce peripeţii va întâmpina eroul nostru AsyncTask?

Conceptul de Async Task este evidenţiat prin intermediul clasei private CitireFisier, din cadrul Activity2.java.  Sunt prezente 3 dintre cele 4 metode care pot fi adaugate, şi anume:  onPreExecute,  doInBackground,  onPostExecute.

  • onPreExecute se ocupă de afişarea progress dialog-ului;
  • doInBackground cuprinde codul dedicat citirii fişierului;
  • onPostExecute : dacă s-a finalizat citirea fişierului, atunci progress dialog-ul va dispărea.

Metoda care lipseşte este onProgressUpdate(Progress…) .  Aceasta este invocată după ce s-a apelat o altă metodă specifică Async Task,  şi anume publishProgress(Progress…). Acesta metodă este utilizată pentru a anima progress dialog-ul şi pentru a modifica modul de afişare (orizontal, vertical, cu procente, mesaj custom, etc.)

Pentru a apela clasa privată şi a pune la muncă metodele create trebuie adăugată  doar o linie de cod şi utilizată o singură dată:
new CitireFisier().execute();

În ceea ce priveşte citirea şi scrierea de fişiere se utilizează clasele şi metodele clasice, dar ca observaţie trebuie să atrag atenţia asupra modului de salvare. Există două posibilităţi: posibilitatea 1 şi posibilitatea 2. 😀

  1. salvare în memoria internă, ceea ce nu permite accesul la fişierele create, iar atunci când aplicaţia este dezinstalată acestea se vor şterge automat, deci nu rămâne spaţiu ocupat (aceasta este şi maniera în care am implementat codul dat ca exemplu), sau
  2. salvarea pe sd card (adică memoria externă, în cazul în care există, deci un dezavantaj) asumându-ne riscul că fişierele pot fi şterse de necunoscători. Pentru mai multe detalii puteţi consulta aici.

Şi a trăit AsyncTask în Ţara Fişierelor,  pe Planeta Android fericit până la adânci bătrâneţi (adică până dezinstalaţi “povestea lui AsyncTask în Ţara Fişierelor ”). Enjoy! 🙂

P.S. : Arhiva cu codul sursă şi APK-ul se găseşte aici. Aştept feedback şi idei pentru noi tutoriale!

via androider.ro

Advertisements
AsyncTask în Ţara Fişierelor, Planeta Android

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s