I am displaying the student details from remote MSSQL database into android using php scripts. The data is displaying fine but it is taking more time to display them i.e until the data is displayed it is showing black screen. How to get the data quickly and where should I make the changes to avoid the black screen?
Thanks in advance.
You should pull the Data Asynchronously. Refer to AsyncTask. If the remote call is so slow you can also think about some caching.
new Thread(new Runnable() {
#Override
public void run() {
//loaddata
}
}).start();
keep in mind that when you want to access the UI Thread you have to use the runOnUiThread method
In Android every App can have a Caching Directory. Its a good way to cache your Data and display this data for the time the fresh data is loading in the Background.
With your Datastructure Serializable you be able to write down your Data into this Caching Directory and speed up your Loading.
Here some Snippeds for Caching data:
private void loadData() {
ObjectInputStream in;
try {
FileInputStream fis = new FileInputStream(new File(getCacheDir(),
"cache.dat"));
in = new ObjectInputStream(fis);
data = (Data) in.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private void saveData() {
if (data.size() > 0) {
File file = new File(getCacheDir(), "cache.dat");
ObjectOutputStream out;
try {
file.createNewFile();
out = new ObjectOutputStream(new FileOutputStream(file));
out.writeObject(data);
out.close();
} catch (IOException e) {
}
}
}
Related
I am trying to save in cache response from server for certain time.
There are tne next data for saving in cache: I have a List<ProgrammeItem> which I am getting from server. While user is working, he can download up to ~230 List<ProgrammeItem> (but it is unreal to reach this, estimated is 10-50).
ProgrammeItem oblect including strings, int, int[].
That is how I am saving and getting the last downloaded List<ProgrammeItem>:
//saving / getting Programme items
public boolean saveObject(List<ProgrammeItem> obj) {
final File suspend_f=new File(android.os.Environment.getExternalStorageDirectory(), "test");
FileOutputStream fos = null;
ObjectOutputStream oos = null;
boolean keep = true;
try {
fos = new FileOutputStream(suspend_f);
oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
} catch (Exception e) {
keep = false;
Log.e("catching exception ", "" + e.getMessage() + ";;;" + e);
} finally {
try {
if (oos != null) oos.close();
if (fos != null) fos.close();
if (keep == false) suspend_f.delete();
} catch (Exception e) { /* do nothing */ }
}
return keep;
}
public List<ProgrammeItem> getObject(Context c) {
final File suspend_f=new File(android.os.Environment.getExternalStorageDirectory(), "test");
List<ProgrammeItem> simpleClass= null;
FileInputStream fis = null;
ObjectInputStream is = null;
try {
fis = new FileInputStream(suspend_f);
is = new ObjectInputStream(fis);
simpleClass = (List<ProgrammeItem>) is.readObject();
} catch(Exception e) {
String val= e.getMessage();
} finally {
try {
if (fis != null) fis.close();
if (is != null) is.close();
} catch (Exception e) { }
}
return simpleClass;
}
That is how I am saving and getting object in activity:
PI = new ProgrammeItem();
List<ProgrammeItem> programmeItems = new ArrayList<>();
...
//filling programmeItems with data from server
...
boolean result = PI.saveObject(programmeItems); //Save object
ProgrammeItem m = new ProgrammeItem();
List<ProgrammeItem> c = m.getObject(getApplicationContext()); //Get object
The question is: how can I save a lot of my objects instead of only one?
I think I should done something like public boolean addObjectsInCache(List<ProgrammeItem> obj) for adding objects, not overriding them.
And change get method into public List<ProgrammeItem> getObject(Context c, String id), where id will be unique identifier, which will includes into every ProgrammeItem in the every List<ProgrammeItem>.
Am I right? And how I can achieve this? Maybe you will show me the other way to work with objects and cache?
You can use SharedPreference instead, while having a local database Android Room can also be an option. SharedPreference basically is stored in your device's cache while the local database is stored in your device's data hence in our apps we have clear cache and clear data function.
Additional Resources:
StackOverFlow: How Android SharedPreferences save/store object
Object based preference library: https://github.com/ShawnLin013/PreferencesManager I would suggest you go with this one, since it can easily save you time saving list based object and retrieving them. You can also add more to the persisted list object when needed.
Secured Preferences: https://github.com/scottyab/secure-preferences
An option could be to use Room database with inMemoryDatabaseBuilder:
db = Room.inMemoryDatabaseBuilder(context, ProgrammeDatabase::class.java)
.build()
if it all can fit in memory.
I'm working on an app which stores small amounts of data in /data/data/my_app/files using this code:
private void buildFileFromPreset(String fileName) {
fileName = fileName.toLowerCase();
StandardData data = StandardData.getInstance();
String[] list = data.getDataByName(fileName);
FileOutputStream fos = null;
try {
fos = openFileOutput(fileName, Context.MODE_PRIVATE);
PrintWriter writer = new PrintWriter(fos);
for (int i = 0; i < list.length; i++) {
writer.println(list[i]);
}
writer.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
All works fine when the app gets started, in the onCreate() function of the main activity, I want to check if the files that were created last time are still present:
private String getAppFilesDir() {
ContextWrapper c = new ContextWrapper(this);
return c.getFilesDir().toString();
}
which returns something like:
/data/user/0/my_app/files
I've read some older posts (2012) suggesting this method must work but it doesn't, probably since jellybean.
So my question:
How can I check if the files I created using FileOutputStream and PrintWriter in a previous session still exist?
I hope I provided enough info for you guys to answer (:
I still have not found a solution for this specific problem.
Instead I am now using SQLite so I don't have to worry about these kinds of things.
Hi Iam having serious issues try to persist some serializable objects to a file on the local android file system. Iam getting a Bad file descriptor error and I think it is to do with my methods for creating the file. the file and checking if the file exists. i create a private file object in the class. Then, on write or read. I check file existance with the following code.
#Override
public boolean fileExists() {
File file = context.getFileStreamPath(filename);
return file.exists();
}
this doesnt instantiate my file object called "objectfile"!! but does check the "filename" exists.
to create the file I call this method if "filename" doesnt exist.
public void createFile()
{
objectfile = new File(context.getFilesDir(), filename);
objectfile.setReadable(true);
objectfile.setWritable(true);
}
Iam not sure if this will give me back my previously created file which would be ideally what I want to do. Is there a way i can just get the old file or create a new one and pass it to "objectfile" variable in the constructor??
Iam also wondering what the best way to do this is??
Or should i just use the mysqlite db? using object file persistance doesn't seem to be working out for me right now and iam working to a deadline. Also this method is mention in the gooogle docs so I thought it would be legit was to do it.
http://developer.android.com/training/basics/data-storage/files.html
here is my method for reading the serializable objects
public synchronized ArrayList<RoomItem> readObjects() {
final ArrayList<RoomItem> readlist = new ArrayList<>();
if(!fileExists())
return readlist;
if(objectfile == null)
createFile();
try {
finputstream = new FileInputStream(objectfile);
instream = new ObjectInputStream(finputstream);
readwritethread = new Thread(new Runnable() {
#Override
public void run() {
try {
final ArrayList<RoomItem> readitems = (ArrayList<RoomItem>) instream.readObject();
instream.close();
finputstream.close();
handler.post(new Runnable() {
#Override
public void run() {
listener.updateList(readitems);
}
});
} catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
Log.d("read failed", "file read failed");
}
}
});
}
catch(Exception e)
{
e.printStackTrace();
}
timeOutReadWrite(readwritethread);
readwritethread.start();
try {
readwritethread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("read from file", "file read");
return readlist;
if anyone could suggest any improvements id really appreciate it. I use a handler to pass back to my activity and implement a listener interface on my activity thats call the activity when all the obj are read. Thanks again!
1#: Yes, it will return the original file you created.
2#: Depends on the thing you want to store, seems File is more flex from description
hope helpful.
We have used
FileOutputStream fos = context.openFileOutput("file.ser", Context.MODE_PRIVATE);
to write our serialized files.This will carete files in /data/data/app.package.name/files/. In fact, this path is returned by getFilesDir().
And while deserializing, use
//make sure you pass the same file that was passed to openFileOutput()..
FileInputStream fis = context.openFileInput("file.ser");
Also, to avoid confusing between file names you can use name of class that is being serialized.
Ex:
public static <T> void serialize(final Context context, final T objectToSerialize) {
....
....
Strin fileName = objectToSerialize.getClass().getSimpleName();
...
}
Do this and keep the method in util so it can be used for any type of objects (T type) to serialize.
I am trying to write and read a text file which is full of words and add it to an ArrayList. The ArrayList later is used from another part of the program to display text in a TextView. But when i run the program and open the specific part of it, then there is nothing. The ArrayList is just empty. I don't get any exceptions but for some reason it doesn't work. Please help me.
I don't seem to have problems with the file writing:
TextView txt = (TextView)findViewById(R.id.testTxt);
safe = txt.getText().toString();
try {
FileOutputStream fOut = openFileOutput("test.txt", MODE_WORLD_READABLE);
OutputStreamWriter osw = new OutputStreamWriter(fOut);
try {
osw.write(safe);
osw.flush();
osw.close();
Toast.makeText(getBaseContext(), "Added to favorites", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException ex){
Log.e("Exception", "File write failed: ");
}
} catch (IOException e) {
Log.e("Exception", "File write failed: ");
}
But I think the problem is in the file reading. I made some "Log.d" and found out that everything works fine till the InputStreamReader line:
public favHacks() {
testList = new ArrayList<String>();
try {
//Works fine till here
InputStreamReader inputStreamReader = new InputStreamReader(openFileInput("test.txt"));
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String receiveString = "";
while ( (receiveString = bufferedReader.readLine()) != null )
{
testList.add(receiveString);
}
bufferedReader.close();
}
catch (FileNotFoundException ex) {
Log.d("login activity", "File not found: ");
} catch (IOException ex) {
Log.d("login activity", "Can not read file: ");
}
}
If you have a relatively small collection of key-values that you'd like to save, you should use the SharedPreferences APIs.
http://developer.android.com/training/basics/data-storage/shared-preferences.html
also if you want to write/read files, or do any kind of operations that can block the Main Thread try to use another Thread like when you are trying to save the data in a file or use a Handler if you have multiple Threads (one for saving and one for reading).
https://developer.android.com/training/multiple-threads/index.html
In your code the method called favHacks can return an ArrayList with the list of all the strings Something like
//
public ArrayList<String> readFromFile(String file){
ArrayList<String> mArrayList= new ArrayList<String>();
//read from file here
return mArrayList;
}
but as I said before, you need to the operations that can block the UI thread in a new Thread.
https://developer.android.com/training/multiple-threads/communicate-ui.html
And also I think that the best way to do this is using Asynk task
Why and how to use asynctask
At first I have strong Java knowledege, but however just started with Android.
My Android app is downloading some fairly complex data (texts, dates, images) which I am saving in a custom object. The data need to be refresh from time to time. However usually the data downloaded will not change.
In order to keep the data in memory I am using the Application Object. Unfortunately, it looks like the application object instance is destroyed when the app is killed.
Hence, I was wondering if it would be of good practice to serialize and save my custom object (which is contained in the application object) in the internal storage during onPause(). Obviously, I would then first read from the file in onResume() before reloading from the internet. The idea is also to enable offline viewing.
In longer term the plan is to move the code downloading the date in a background service. As there seems to be many different ways to keep application state in Android, I would like to be be sure that this is the correct way to go.
Try using those methods class to save the Object(s) (implements serialize) you need:
public synchronized boolean save(String fileName, Object objToSave)
{
try
{
// save to file
File file = new File(CONTEXT.getDir("filesdir", Context.MODE_PRIVATE) + "/file.file");
if (file.exists())
{
file.delete();
}
file.getParentFile().mkdirs();
file.createNewFile();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(objToSave);
oos.close();
return true;
}
catch (FileNotFoundException e)
{
e.printStackTrace();
return false;
}
catch (IOException e)
{
e.printStackTrace();
return false;
}
}
public synchronized Object load(String fileName)
{
try
{
File file = new File(CONTEXT.getDir("filesdir", Context.MODE_PRIVATE) + "/file.file");
if (!file.exists())
{
return null;
}
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
savedObj = ois.readObject();
ois.close();
return savedObj;
}
catch (FileNotFoundException e)
{
e.printStackTrace();
return null;
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
You'll need to cast the Object you load().
CONTEXT is an Activity or ApplicationContext to get access to the cachedir.
Your could use Environment.getExternalStorageState() instead to get a directory path. DOn't forget to add it "/filename".