piątek, lipca 16, 2010

Książeczki :-)

Ponieważ nie chciałem płacić 75 złotych za kartę kredytową to wybrałem się do Amazon.co.uk w celu zwiększenia obrotów ;-) (nie ma to jak racjonalizować ;-))

No i dziś przyszła nagroda (po przejściach z DHL), oto ona :-)

Teraz można będzie zacząć czytać :-)



Podobne postybeta
Marudzenie nocne ;-)
Tęcza :-)
Wirtualna wycieczka po Los Angeles :-)
Noble
Jak uniknąć zonka ;-)

środa, lipca 14, 2010

Modale nie takie dobre dla Androida ;-)

W niedzielę pisałem o oknach modalnych i zaprezentowałem jak można w Androidzie zrobić sobie okno modalne, które blokuje przepływ, a więc upraszcza też logikę aplikacji.........Niestety rozwiązanie, które sprzedałem ma pewien problem.W Androidzie konfiguracja sprzętu może zmieniać się w locie, głównie chodzi o orientację ekranu [choć nie zdziwiłbym się jakby za jakiś czas doszła też zmiana ekranu ;-) gdy np. pojawią się tablety ze złączem HDMI].Taka zmiana powoduje zaś odrysowanie UI aplikacji. Oznacza to tyle, że nasza stara aktywność jest niszczona, a nowa jest uruchamiana i wołane są jej metody onCreate() a następnie onResume().Niestety to odrysowywanie UI ma też konsekwencję dla okien dialogowych. Znikają.Moja metoda polegała na tym, że tworzyłem okno dialogowe, które z wątkiem "głównym" komunikowało się przez pewien obiekt, a żeby wątek "główny" głupio procesora nie żarł to czekał na monitorze związanym z obiektem do przekazywania rezultatów. Naciśnięcie któregoś z klawiszy dialoga powodowało zaś ustawienie rezultatu, a następnie zawołanie notifyAll() na tym obiekcie dzięki czemu wątek "główny" był budzony i sterowanie wracało do naszego zatrzymanego kodu.Rozwiązanie genialne ;) ale ma wadę.Ponieważ dialog znika po zmianie orientacji ekranu to zostajemy z ekstra wątkiem [tym "głównym", który czeka na wynik dialoga], który wisi i czeka na obiekcie rezultatu. Nie zostanie on jednak nigdy celowo obudzony przez nasz kod, a nawet jeśli się to jakoś zdarzy to po sprawdzeniu, że użytkownik nie kliknął na żaden z guziczków dialoga wróci do czekania na obiekcie rezultatu.Dodatkowo w pamięci będą siedziały też wszystkie obiekty używane przez nasz wątek, czyli aktywność dla której stworzono i pokazano dialog [ta aktywność, która została "zamknięta" po zmianie orientacji] i wszystko co zostało już jakoś w tym wątku użyte...... a ponieważ wątek to zwykle wewnętrzna klasa anonimowa i to taka złośliwa, że nie jest statyczna (dla przypomnienia, wewnętrzna klasa musi mieć dodatkowe mechanizmy do trzymania kontaktów z klasą zewnętrzną, dlatego gdy chcemy mieć klasę wewnętrzną, a nie wymaga ona związku z klasą zewnętrzną to używamy modyfikatora static do zerwania tego łącza co wpływa na performance ;-)) więc trzymamy w pamięci de facto wszystko związane ze starą aktywnością......... A to nie jest fajne.Dlatego mimo wszystko odradzam używanie mojego confirm() :-)Co prawda nie jest do końca powiedziane, że nie da się tego obejść ;-) wystarczyłoby sprawić by wątek "główny", który czeka na rezultat nie robił wait() a robił wait(int), czyli czekał przez zadany czas, po czym sprawdzałby czy jego aktywność w ogóle działa i jeżeli by działała wracałby do czekania, a w przeciwnym przypadku wywalałby wyjątek..... nie jest to ładne, ale dalej pozwoliłoby się cieszyć w miarę wygodnym confirm().Ale jak na razie moje próby ugryzienia problemu spełzły na niczym bo nie potrafię wykryć tego stanu gdy aktywność została zgubiona........Z dodatkowych bonusów, także ProgressDialog na to choruje, tzn. znika po zmianie orientacji ekranu :-( Jeżeli kontroluje go jakiś zewnętrzny wątek to wątek ten nadal sobie biegnie, ale już jego aktywność nie żyje, a dokładniej nie żyje tak jak powinna ;-) dlatego zawołanie na niej np. finish() spowoduje wywalenie wyjątku......Android trudny.......


Podobne postybeta
Modale dobre - confirm dla Androida :-)
Prototypowanie dla Androida
O wyższości klas anonimowych
wait() i notify()/notifyAll() - najbardziej nierozumiane metody klasy Object ;-)
O tym w czym iOS jest lepszy od Androida

Blogowanie z Androida z obrazkami 2 :-)

Poprzednia wersja mojego programu do blogowania miała błąda ;-) zamiast miniaturki wrzucała jako link do miniaturki link do pełnego obrazka.

To tutaj to znów test :-) tym razem widok z mojego miejsca spania w Krakowie :-)



Podobne postybeta
No i potrafię już blogować z Androida z obrazkami :-)
Nie kłóć się z użytkownikiem! ;-)
Wytrzymałość baterii w EEE Pad Transformer - test przy pomocy "potworów" ;-)
Nigdy nie zapominaj o FSM! ;-)
Geolokalizacja postu z obrazka, czyli nie taki Exif zły :-)

No i potrafię już blogować z Androida z obrazkami :-)

Poniższy obrazek nie ma nic wspólnego z postem, poza tym, że jest obrazkiem :-)

Dla ciekawych to była kiedyś jedna z fontann w Wodzisławiu Śląskim, podobno działała przez kilka miesięcy w latach 70 :-)

Jeżeli ten post się opublikuje będzie to znaczyło, że moja aplikacja do blogowania dla Androida, którą sobie piszę potrafi uploadować już obrazki :-)

Jak na razie jeden i trzeba blogowanie zacząć z Galerii, ale pierwsze koty za płoty :-)

Ze złych wiadomości z tego co widzę za oknem wkrótce będzie świtać ;-)

Jak ktoś ciekawy to aplikacja zajmuje teraz 25.5 KB :-)




Podobne postybeta
Nowy Gadacz v0.2
Ktoś instalował Androida 2+ na G1?
Dzielenie się z Bloggeroida...
Bloggeroidujemy ;-)
Piszemy sobie Bloggeroida dla Androida ;-)

wtorek, lipca 13, 2010

Czekamy na kalkulator :-)

Czaiłem się na kalkulator od roku albo i dłużej, ale w końcu zamówiłem sobie Casio Algebra FX 2.0 Plus :-)

Teraz tylko męczę serwer sprzedawcy sprawdzając czy już zmienił się status mojego zamówienia :-)

Na razie ciągle jest to zły stan ;-)

Podoba mi się to, że kalkulator ten ma tryb pracy CAS. Nie żeby był mi on jakoś niezbędnie potrzebny, ale miło będzie go mieć :-)

Nie zdecydowałem się na zakup kabelka do podłączania kalkulatora do PC, głównie przez to, że i tak nie mam nigdzie RS232, a nie czuję bluesa by kupować adapter USB-RS232.

Będzie nowa zabawka :-)



Podobne postybeta
Kalkulator
Kalkulator marzeń ;-)
Małe USB jest wielkie :-)
Kiedy tablet zmieni się w dobry kalkulator?
Strzeż się uses-feature

Taki mały sekret, czyli jak to czasem lubie się pobowaić user experience ;-)

Z serii wstydliwe wyznania ;-)
Ostatnio zauważam u siebie z niepokojem to, że dziką satysfakcję powoduje u mnie taka prosta analiza user experience i dążenie do tego by przestrzegać zasady najmniejszego zdziwienia.
Nie twierdzę, że mi się to udaje. Ale co dodaję jakiś nowy ficzer do aplikacji [swojej lub pracowej] to próbuję zaatakować rozwiązanie związane z UX od strony prześledzenia wszystkich możliwych przypadków użycia i jak się da to staram się wyrzucać te nadmiarowe.
I nawet chyba efekty widać ;-)
Ja, czyli ktoś kto nie znosi pracować nad UI, myślę o tym i próbuję to robić dobrze......... przerażające ;-)
Mam tylko nadzieję, że moje pomysły nie są później przerażające dla użytkowników ;-)

Podobne postybeta
Google I/O 2021....
Walka z DDE
O ziarenkach
Polski to nie jest dobry język do internetu ;-)
Jestem anonimowym programistą....

Wkurzają mnie obłudni i źli hipokryci mizogini.

Z dwa dni temu na National Geographic HD oglądałem film Koran, o jak się łatwo domyśleć Koranie właśnie. Dziś w TVP Info widziałem kawałki programu o problemie gwałtów w wielu państwach afrykańskich.Wczoraj znów na WP i Onecie pojawiły się newsy o sondażach dotyczących akceptacji aborcji [tutaj zresztą ciekawa sprawa, w Onet tytuł był "Sondaż: połowa Polaków przeciw aborcji" na WP za to "Prawie połowa Polaków chce prawa do aborcji", w Onecie tytuł zawierał sugestię, że Połowa Polaków jest przeciwko aborcji, a WP, że mniej niż połowa akceptuje aborcję, choć w samych "artykułach" [były chyba identyczne bo jak przypuszczam były to po prostu newsy z PAP czy czegoś podobnego] była mowa o tym, że przeciwne aborcji jest chyba 14% populacji, reszta dopuszcza aborcję z różnymi ograniczeniami, a ta połowa z obu tytułów oznacza po prostu, że blisko 50% Polaków jest za dopuszczalnością aborcji z przyczyn społecznych, czyli takiej gdzie kobieta jeżeli uzna, że to będzie najlepsze rozwiązanie, może pójść i dokonać zabiegu].I tak patrząc na to, czy czytając zastanawiam się nad tym jak można być tak obłudnym, jak można być takim hipokrytą.Obłudnym jak pan kapłan w tym filmie Koran, który uzasadnia jedną z najbardziej barbarzyńskich praktyk na naszej planecie, czyli obrzeżanie kobiet [obrazowo, dziewczynkom tak zwykle od 8 do 13 roku życia wycina się łechtaczkę przy pomocy "domowych sposobów" po czym wiąże się jej nogi na parę tygodni żeby wszystko się zagoiło i zarosło. Radzę to przeczytać kilka razy żeby dotarło jakie to jest okropieństwo. Jaki to musi być ból, jakie musi zostawić ślady na psychice. Mówiąc jeszcze inaczej, niezależnie jakie okropieństwa przeżyłeś czy przeżyłaś w Polsce, na 99.999% nie były one tak straszne jak to co robi się wielu dziewczynkom na świecie w imię chorego przekonania, że dzięki temu będą bardziej cnotliwe] bo są dzięki temu bardziej cnotliwe........ [specjalnie nie piszę tu o braku higieny w trakcie takich "zabiegów" bo to szczegół, kara śmierci nie staje się bardziej humanitarna prze to, że skazańcowi się wstrzyknie truciznę strzykawką jednorazową, jest tak samo barbarzyńska jak taka gdzie rozrywa się go końmi. Tak samo w przypadku tego obrzezania nie jest istotne czy robi się to przy pomocy kawałka szkła czy noża, na klepisku czy w sali operacyjnej]Obłudy "obrońców życia", którzy praktycznie zawsze budują w naszych głowach obraz kobiet, które poddają się aborcji jako "puszczalskich" bo przecież "pies nie weźmie jak suka nie da". Obłudy która stawia na piedestale zarodek czy płód, a gnoi kobietę.Tak btw. sondaży to w sprawie aborcji powinny się mieć prawo wypowiadać tylko kobiety, to ich ciała.Ta obłuda sugerująca, że kobiety są złe, puszczalskie, nieczyste, amoralne. Ten obraz tworzony przez bandę ludzi z obsesją na punkcie seksu. Zresztą tak przy okazji, wielu zwolenników prawicy nienawidzi islamu, co jest o tyle śmieszne, że poglądy na wiele spraw związanych z seksem to chrześcijaństwo ma bardzo zbieżne z islamem, bo "moralność chrześcijańska" w swojej pierwotnej postaci to przecież twór ludzi żyjących w podobnej kulturze jak tych, którzy później tworzyli islam. Chrześcijaństwo to moralność i zwyczaje przyniesione z bliskiego wschodu, wzbogacone o tytuły z Rzymu (Ponitfex Maximus to był kierownik kapłanów w Rzymie, i teraz tym kierownikiem jest papież), ok jeszcze trochę błyskotek i symboliki zostało z rzymskich.Dlatego stwierdzam wszem i wobec, że rzygać mi się chce jak widzę moralistów mówiących pięknymi słowami rzeczy, które mają tłumaczyć ich mizoginię.Najlepiej to podsumowuje dowcip, który brzmi tak:- Kto to jest puszczalska?- Kobieta podchodząca do spraw seksu tak jak przeciętny mężczyzna.Dla ludzi, którzy nie zrozumieli aluzji. Jeżeli coś wolno facetowi, to wolno to i kobiecie. Koniec kropka, nie podoba się? No to masz problem.

Podobne postybeta
In vitro
Kopernik i zasada kopernikańska, później Darwin i Teoria Ewolucji... co będzie kolejne? Silne AI czy synetyczne życie?
Studia wyższe
Czerwcowe książki
O Android Market

Google App Inventor for Android - co to będzie? ;-)

Zapisałem się na konto w Google App Inventor for Android, najnowszym pomyśle Google, czyli narzędziu które nie programistom da możliwość pisania prostych aplikacji.

Ciekawe czy i kiedy dostanę konto ;-)

Nie wiem do końca co o tym sądzić. Z jednej strony pomysł genialny, z drugiej jak widziałem w filmie pokazującym tą aplikację wynikowa aplikacja nie poraża ;-)

Przez część blogów przetacza się fala obaw, że takie wyklikane aplikacje mogą zalać Android Market i obniżyć jakość aplikacji.

Coś w tym jest (tutaj trzeba powiedzieć jedno "ale" :-) nie publikowałem jeszcze żadnych moich aplikacji w Android Markecie, ale zdarzyło mi się już to robić z rozszerzeniem dla Chrome, i w przypadku rozszerzenia konieczne było zuploadowanie kodu źródłowego... możliwe więc, że i Android Market tego wymaga, a wtedy nie powinno być takiego zalewu słabych aplikacji), bo nawet teraz gdy do publikacji aplikacji na Android Market trzeba wykazać się choć minimalnymi umiejętnościami, mamy tam wiele słabych programów.

Z drugiej jednak strony takie otwarcie to szansa na małe użyteczne cosie :-)

To użytkownicy wiedzą czego im brakuje i tutaj dostaną do swoich rąk zabawkę do zbudowania tych brakujących rzeczy.

Myślę, że wprowadzenie po prostu w markecie nowej kategorii aplikacji wyklikanych pozwoliłoby na to by wilk był syty i owca cała :-)




Podobne postybeta
Zakaz handlu w niedzielę jest głupi
Traf to za userem... ;-)
OO.org i Google Docs bez konwersji są tuż tuż ;-)
Jak się topologicznie wprowadzać ;-)
Markety

niedziela, lipca 11, 2010

Modale dobre - confirm dla Androida :-)

Dla niezorientowanych, w komputerach mamy 2 typy okienek z komunikatami. Okienka modalne i niemodalne.
Modalne to takie, które blokują interfejs użytkownika i często też przepływ programu, niemodalne to takie, które niczego nie blokują.
Zwykle niemodalne są lepsze.
Jest jednak kilka sytuacji gdy okienka modalne w najbardziej klasycznej wersji ułatwiają życie.

W JavaScrip'cie możemy mieć taki fragment:
if (confirm("Czy mam coś zrobić?")) {
// coś robię
}

Który wyświetli modalne okienko z pytaniem "Czy mam coś zrobić", jeżeli użytkownik odpowie tak to zostanie wykonany kod opisany jako "coś robię".

Jeżeli jednak użyjemy okienka niemodalnego to już tak prosto nie jest:
function code4Yes() {
// coś robię
}
myConfirm("Czy mam coś zrobić?",{onYes:code4Yes});


Jeszcze gorzej w takim przypadku:
if (confirm("Czy mam coś zrobić?")) {
// coś robię
} else {
// robię coś innego
}
// robię część wspólną


Bo wtedy rozwiązanie niemodalne się jeszcze bardziej komplikuje:

function restOfOperations() {
// robię część wspólną
}
function code4Yes() {
// coś robię
restOfOperations();
}
function code4No() {
// robię coś innego
restOfOperations();
}
myConfirm("Czy mam coś zrobić?",{onYes:code4Yes,onNo:code4No});


W JavaScript możemy po prostu nie chcieć użyć confirm bo okienko jest brzydkie, ale w takim Androidzie sprawa ma się tak, że po prostu nie wolno nam użyć "klasycznego" modala :-(
Tak się składa, że nie możemy z wątku nie związanego z UI nic z tym UI robić. W ogóle w modelu wątków/pamięci Java'y trudno byłoby zrealizować takie zachowanie jak to z klasycznym confirm.

Spróbowałem sobie coś takiego zakodować przed chwilą i okazało się to być jeszcze bardziej skomplikowane od rozwiązania z okienkiem modalnym, którego używa się normalnie ;-)

final StringBuilder sb = new StringBuilder();
v.post(new Runnable() {
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(AddAccount.this);
builder.setMessage("I know this account!\nDo you want me to refresh list of blogs for this account?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
synchronized (sb) {
sb.append("1");
}
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
AddAccount.this.finish();
}
});
AlertDialog alert = builder.create();
alert.show();
}
});
while (1==1) {
Log.i("toster", "waiting....");
synchronized (sb) {
if (sb.length()>0) {
Log.i("toster","done :-)");
break;
}
}
try {
Thread.sleep(100);
} catch (InterruptedException ie) {

}
}

W tym kodzie jest na dodatek błąd, który spowodowałby, że w razie kliknięcia przez użytkownika "No" watek sprawdzający długość StringBuildera nadal by biegał, nawet po zamknięciu aktywności ;-)
Bardziej klasycznie to powinno wyglądać tak:
v.post(new Runnable() {       
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(AddAccount.this);
builder.setMessage("I know this account!\nDo you want me to refresh list of blogs for this account?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.i("toster","done :-)");
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
AddAccount.this.finish();
}
});
AlertDialog alert = builder.create();
alert.show();
}
});


To poprzednie rozwiązanie z blokowaniem przepływu można by było jednak tak ubrać by wyglądało to tak, że wołalibyśmy tylko confirm, które już wewnętrznie tworzyłoby StringBuildera [albo StringBuffera czy coś innego, StringBuffer pozwoliłby nam wywalić synchronizację ;-)] oraz ukrywał przed oczami kodera to sprawdzanie czy button został kliknięty.
Dla kodera wyglądałoby to jak klasyczny confirm z JavaScript. Czyli wykonanie kodu zostałoby wstrzymane do momentu gdy użytkownik nie kliknąłby na Yes.
Na pewno byłoby to rozwiązanie brzydkie od strony czytelności kodu, ale zdecydowanie ułatwiałoby to życie ;-)

Zakodowałem to i kod wygląda teraz tak:
private boolean confirm(final String msg) {
class Result {
int result;
};
final Result result = new Result();
runOnUiThread(new Runnable() {
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(AddAccount.this);
builder.setMessage(msg)
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
synchronized(result) {
result.result=1;
result.notifyAll();
}
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
synchronized(result) {
result.result=2;
result.notifyAll();
}
}
});
AlertDialog alert = builder.create();
alert.show();
}
});
while (result.result==0) {
synchronized (result) {
try {
result.wait();
} catch (InterruptedException e) {
// OK, nothing important happen
}
}
}
}


Wywołanie takiego kodu mogłoby wyglądać wtedy tak:
if (confirm("I know this account!\nDo you want me to refresh list of blogs for this account?")) {
Log.i("toster","done :-)");
}


Zwróćcie uwagę na przebiegłe wykorzystanie wait i notifyAll ;-)
Mój confirm działa tak, że przy użyciu przekazanego widoku wątek UI proszony jest o wykonanie kodu, w którym tworzony i wyświetlany jest dialog. W tym samym czasie wątek "proszący" sprawdza czy zwrócono jakiś rezultat, a jeżeli nie zwrócono to synchronizuje się na obiekcie rezultatu i mówi JVM "poczekam sobie na monitorze podpiętym do result". JVM przesuwa ten wątek do śpiących/czekających. W tym samym czasie jakiś wątek UI obserwuje czy użytkownik nie kliknął nam na któryś z guziczków, jeżeli klikną to wywoływany jest kod anonimowych listenerów, które działają w taki sposób, że synchronizują się na obiekcie rezultatu, ustawiają odpowiednią wartość na tym rezultacie i wysyłają notifyAll() budząc wszystkie wątki czekające na monitorze podpiętym do result. W tym momencie nasz wątek jest budzony i zaczyna znów biec.

Ktoś mi powie czemu takie rozwiązane jest złe? Czy może jest OK? A jeżeli jest OK to dlaczego nie ma czegoś takiego "w standardzie"? :-)


Podobne postybeta
Modale nie takie dobre dla Androida ;-)
Przepływ sterowany danymi - A takie Java'owe coś ;-)
wait() i notify()/notifyAll() - najbardziej nierozumiane metody klasy Object ;-)
Potfór ;-) czyli generator z yield w Java'ie
Sztuczki tropiciela błędów, part 4