Tuesday, June 29, 2010

Re: [android-developers] Re: Best httpclient re-use stategy

On Mon, Jun 28, 2010 at 1:31 PM, David <dagomox@gmail.com> wrote:
Ok, thanks for this advice. So you decide to manage preference by yourself using the filesystem directly ?

I only do it for the two(2) "preferences" where I frequently do a write. For 99% of my preferences I still use the normal preferences.

Just in case you want to have a look at it, this is my code. Please be aware that for every preferences I keep a reference to the file descriptor. This code is not meant for a case where you maintain 2,000 preferences ;)

package com.newsrob.util;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Map;

import android.content.Context;

public class SingleValueStore {

    private Context ctx;
    private Map<String, File> files = new HashMap<String, File>();

    public SingleValueStore(Context context) {
        this.ctx = context.getApplicationContext() != null ? context.getApplicationContext() : context;
    }

    public String getString(final String key) {
        File f = getFile(key);
        if (!f.exists())
            return null;

        RandomAccessFile raf = null;
        String s = null;

        try {
            raf = new RandomAccessFile(f, "r");
            s = raf.readLine();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } finally {
            if (raf != null)
                try {
                    raf.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
        return s;

    }

    public void putString(final String key, final String value) {
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(getFile(key), "rw");
            raf.writeBytes(value + "\n");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (raf != null)
                try {
                    raf.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    public void putLong(final String key, final Long value) {
        putString(key, String.valueOf(value));
    }

    public Long getLong(final String key) {
        return getLong(key, null);
    }

    public Long getLong(final String key, final Long def) {
        String s = getString(key);
        if (s == null)
            return def;
        try {
            return Long.parseLong(s);
        } catch (NumberFormatException nfe) {
            return def;
        }
    }

    private File getFile(String key) {
        if (!files.containsKey(key))
            files.put(key, new File(ctx.getFilesDir(), "svs_" + key));
        return files.get(key);
    }

}

package com.newsrob.test.unit;

import java.io.File;

import android.content.Context;
import android.test.InstrumentationTestCase;

import com.newsrob.util.SingleValueStore;

public class SingleValueStoreTests extends InstrumentationTestCase {

private SingleValueStore svs;
private Context ctx;

@Override
protected void setUp() throws Exception {
super.setUp();
ctx = getInstrumentation().getTargetContext();
svs = new SingleValueStore(ctx);

for (File f : ctx.getFilesDir().listFiles())
if (f.getName().startsWith("svs_"))
System.out.println("Removed " + (f.getName() + f.delete()));
}

public void testSaveAndRestoreString() {
svs.putString("key1", "val1");
assertEquals("val1", svs.getString("key1"));
}

public void testSaveAndRestoreStringWithNewInstance() {
svs.putString("key2", "hello");
svs = new SingleValueStore(ctx);
assertEquals("hello", svs.getString("key2"));
}

public void testValueNotThere() {
assertNull(svs.getString("null"));
}

public void test1000() {
svs.putString("key", "value");
for (int i = 0; i < 1000; i++) {
assertEquals("value", svs.getString("key"));
}
}

public void testOverwriteValue() {
svs.putString("key", "value1");
assertEquals("value1", svs.getString("key"));
svs.putString("key", "value2");
assertEquals("value2", svs.getString("key"));
}

public void testLong() {
svs.putLong("key", 100l);
assertEquals(Long.valueOf(100l), svs.getLong("key"));
}

public void testLongWithDefault() {
assertEquals(Long.valueOf(-99l), svs.getLong("non-existing-key", -99l));
}

}




On Fri, Jun 25, 2010 at 10:48 PM, Mariano Kamp <mariano.kamp@gmail.com> wrote:
Just a sidenote on an issue that you touch, but not the actual main issue: 

> - Save the cookie (String serialized into SharedPreferences) and
> create every time a new httpclient instance (then set the cookie to
> the new instance) => overhead to get the http connection
I tried that in my app and found out there is a huge performance penalty involved as compared to just writing it to a file directly. I got the impression if you set any preference and do a commit, then all the settings are serialized into one single XML file and that's written to the very slow flash memory. If you have, say 50 other settings, this may take 300-600ms vs. 15 ms. Don't get hung up on the the actual numbers, just see the difference in principle here. 
Also when you have other stuff (the stream?) that you want to write, then you're also clogging the flash memory.

On Fri, Jun 25, 2010 at 4:46 PM, MoxFulder <dagomox@gmail.com> wrote:
nobody has any idea ?

On Jun 21, 10:33 am, MoxFulder <dago...@gmail.com> wrote:
> Hi there,
> I'm new using android sdk/httpclient
>
> I'm writing a small application which needs httpclient lib, basically
> to manage the cookie/session automatically.
> The website I'm targeting needs a valid session, so, between each http
> call, I need to send the cookie. Httpclient does it well. This is a tv
> stream application and I have to fetch the channel url, the url has a
> token parameter and I have to be logged / authenticated / (=> have a
> valid cookie/sessionid) to fetch the channel url.
>
> I got the first cookie/sessionid with the first connection to the
> website. The cookie is valid for a certain amount of time, there is no
> "expires" but I don't know if there is any server cron to cleanup the
> sessions. I assume I have to "ping" every x secondes to maintain the
> session valid.
>
> Between each http call, the time could be from 1 sec to several
> minutes, it depends if the user wants to change the watched tv
> channel. The http call (to fetch the url) is not made by the UI
> Thread.
>
> There are several possibilities to manage the httpclient :
> - a single httpclient static singleton instance accessed by a custom
> synchronized getClient() on an helper class => when / how to release
> the http connection ? How to handle that correctly if the user got a
> phone call / does not use the application for now (unvalidate during
> onResume, etc)?
> - Save the cookie (String serialized into SharedPreferences) and
> create every time a new httpclient instance (then set the cookie to
> the new instance) => overhead to get the http connection
> - other ?
>
> I'm asking here what is the best way to implement that.

--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

No comments:

Post a Comment