How to use FFImageLoading in ViewWillAppear? - xamarin.ios

I want to show a UIImageView in the top bar with an UIImage from a url and then cache it in my iOS native Xamarin iOS app. The problem is that when added to ViewWillAppear the FFImageLoading log shows that the image is being cancelled about 9 times out of 10, but occasionally it will succeed and display. I use:
ImageService.Instance.LoadUrl(url)
.Retry(3, 200)
.Into(avatarImage);
It either succeeds on first attempt or all retries fails (I also tried with a longer retry delay with no success). If I put the code in ViewDidAppear it works 9 times out of 10, but not always and never on first load. If I put it into a button that I push after the view has loaded the image is always loaded successfully. So it seems pretty obvious that FFImageLoading is failing because the UIImageView has not yet been drawn/loaded, but as I have created the UIImageView and added it to the View I don't know what more I can do.
How can I use FFImageLoading to load the image reliably? I can preload it, but that still doesn't solve how I get it into the UIImageView before it is displayed for the first time. If impossible with FFImageLoading I'm open to alternatives.
Log: fails to load into UIImageView:
[0:] FFImageLoadingDebug_SimpleDiskCache path: /var/mobile/Containers/Data/Application/93D1FA0C-B19A-4ECA-A0DA-B0AC408A5B8E/Library/Caches/FFSimpleDiskCache
Thread started: <Thread Pool> #3
Thread started: <Thread Pool> #4
Thread started: <Thread Pool> #5
Thread started: <Thread Pool> #6
Thread started: #7
Thread started: <Thread Pool> #8
Thread started: <Thread Pool> #9
Thread started: #10
Thread started: #11
Thread started: <Thread Pool> #12
Thread started: <Thread Pool> #13
[0:] FFImageLoadingDebug_Image memory cache size: 401,5 MB
[0:] FFImageLoadingDebug_Image loading cancelled: https://assets-cdn.github.com/images/modules/logos_page/Octocat.png;CircleTransformation,borderSize=0,borderHexColor=
[0:] FFImageLoadingDebug_Generating/retrieving image: https://assets-cdn.github.com/images/modules/logos_page/Octocat.png;CircleTransformation,borderSize=0,borderHexColor=
[0:] FFImageLoadingDebug_Wait for similar request for key: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
[0:] FFImageLoadingDebug_Wait for similar request for key: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
[0:] FFImageLoadingDebug_Wait for similar request for key: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
[0:] FFImageLoadingDebug_Generating/retrieving image: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
Thread started: #14
[0:] FFImageLoadingDebug_Wait for similar request for key: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
[0:] FFImageLoadingDebug_Image loading cancelled: https://assets-cdn.github.com/images/modules/logos_page/Octocat.png;CircleTransformation,borderSize=0,borderHexColor=
[0:] FFImageLoadingDebug_File /var/mobile/Containers/Data/Application/93D1FA0C-B19A-4ECA-A0DA-B0AC408A5B8E/Library/Caches/FFSimpleDiskCache/CD275DFA133499968568338D6D522382.864000 saved to disk cache for key CD275DFA133499968568338D6D522382
[0:] FFImageLoadingDebug_Image loaded from cache: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
etc.
Log: Succeeds (same page after reloading a few times):
[0:] FFImageLoadingDebug_Image loaded from cache: https://assets-cdn.github.com/images/modules/logos_page/Octocat.png;CircleTransformation,borderSize=0,borderHexColor=
[0:] FFImageLoadingDebug_Image loaded from cache: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
etc.

Refer to the official sample. It may be helpful.
var taskImage = ImageService.Instance.LoadUrl(imageURL)
.ErrorPlaceholder("error.png", ImageSource.ApplicationBundle)
.LoadingPlaceholder("placeholder", ImageSource.CompiledResource);
if(transformation==0)
{
taskImage.Into(imageView);
transformation++;
}
else if(transformation==1)
{
taskImage.Transform(new CircleTransformation()).Into(imageView);
transformation++;
}
else if(transformation==2)
{
taskImage.Transform(new RoundedTransformation(10)).Into(imageView);
transformation = 0;
}

I have been unable to figure out why FFImageLoading gets cancelled, so instead I used Akavache and HttpClient to roll my own (I also use CrossConnectivity to check if mobile is connected).
This works every time when updated from ViewWillAppear. Because I use an IObservable it is important to update the image on the main UI thread, i.e. InvokeOnMainThread.
UrlImageView class used to add a UIView that can load the image from an Url:
public class UrlImageView : UIImageView
{
private GetImageFromUrlObserver getImageFromUrlObserver = null;
public UrlImageView() : base()
{
getImageFromUrlObserver = new GetImageFromUrlObserver(this);
}
public void GetImageFromUrl(string url)
{
if (getImageFromUrlObserver != null)
{
getImageFromUrlObserver.GetImage(url);
}
}
public void Update(byte[] image)
{
this.InvokeOnMainThread(() =>
{
var data = NSData.FromArray(image);
this.Image = UIImage.LoadFromData(data);
});
}
}
The IObserver class (when the image data is retrieved it will trigger OnNext)
public class GetImageFromUrlObserver : IObserver<byte[]>
{
private UrlImageView urlImageView;
private IDisposable unsubscriber;
public GetImageFromUrlObserver(UrlImageView view)
{
urlImageView = view;
}
public void GetImage(string url)
{
Subscribe(ImageLoader.GetImageFromUrl(url));
}
private void Subscribe(IObservable<byte[]> provider)
{
if (provider != null)
unsubscriber = provider.Subscribe(this);
}
public void OnCompleted()
{
Unsubscribe();
}
public void OnError(Exception error)
{
throw new NotImplementedException();
}
public void OnNext(byte[] image)
{
if (urlImageView != null)
{
urlImageView.Update(image);
}
}
private void Unsubscribe()
{
if (unsubscriber != null)
{
urlImageView = null;
unsubscriber.Dispose();
unsubscriber = null;
}
}
}
HttpClient class that gets the image data:
public static class ImageLoader
{
public static IObservable<byte[]> GetImageFromUrl(string url)
{
IObservable<byte[]> result = null;
var httpClient = new HttpClient(new NativeMessageHandler());
});
try
{
var cache = BlobCache.LocalMachine;
result = cache.GetAndFetchLatest(
url, /* simply use url as cache key */
async () =>
{
try
{
if (!CrossConnectivity.Current.IsConnected) return null;
HttpResponseMessage httpResponse = await httpClient.GetAsync(url);
return await httpResponse.Content.ReadAsByteArrayAsync().ConfigureAwait(false); ;
}
catch (Exception e)
{
EventTrackers.TrackException("GetImageFromUrl inner - " + e.Message);
return null;
}
},
offset =>
{
TimeSpan elapsed = DateTimeOffset.Now - offset;
return elapsed > new TimeSpan(hours: cacheUpdateFrequencyHours, minutes: cacheUpdateFrequencyMinutes, seconds: 0);
}
);
}
catch (Exception e)
{
EventTrackers.TrackException("GetImageFromUrl - " + e.Message);
return null;
}
return result;
}
To display the image you call:
UrlImageView image = new UrlImageView();
View.AddSubview(image);
image.GetImageFromUrl(url);

Related

How to properly close a flowable and close response body using rxjava and retrofit

I am attempting to close a stream coming from an http request using Retrofit and rxjava, either because it timedOut, or because I need to change details that went into the request. Both appear to work perfectly, as when I cancel subscription I get the doOnCancel debug message and when doOnNext is completed I get the doOnTerminate message. I also do not receive inputLines from multiple threads. However, my thread count rises every single time either of the above actions happen. It appears that responsebody.close is not releasing their resources and therefore the thread is not dying (I also have gotten error messages along the lines of "OKHTTP leaked. did you close youre responseBody?")
Does anyone have any suggestions?
public boolean closeSubscription() {
flowableAlive = false;
subscription.cancel();
return true;
}
public void subscribeToFlowable() {
streamFlowable.observeOn(Schedulers.newThread()).subscribeOn(Schedulers.newThread())
.doOnTerminate(() -> log.debug("TERMINATED")).doOnCancel(() -> log.debug("FLOWABLE CANCELED"))
.subscribe(new Subscriber<ResponseBody>() {
#Override
public void onSubscribe(Subscription s) {
subscription = s;
subscription.request(Long.MAX_VALUE);
}
#Override
public void onNext(ResponseBody responseBody) {
log.debug("onNext called");
String inputLine;
try (InputStream inputStream = responseBody.byteStream()) {
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
while (flowableAlive && ((inputLine = br.readLine()) != null)) {
log.debug("stream receive input line for thread " + name);
log.debug(inputLine);
}
} catch (IOException e) {
log.debug("error occurred");
log.debug(e.getMessage());
}
}
#Override
public void onError(Throwable t) {
log.debug("error");
flowableAlive = false;
}
#Override
public void onComplete() {
log.debug("completed");
closeSubscription();
flowableAlive = false;
}
});
}
The result of subscribe() is Disposable object. You should store it as a filed and call Disposable.dispose() on it later as shown here:
https://proandroiddev.com/disposing-on-android-the-right-way-97bd55cbf970
Tour OkHttp call will be interrupted properly because dispose() interrupts thread on which the call runs and OkHttp checks regularly if Thread was interrupted to stop transfer when that happened - it's called cooperative cancelling/interruption.

Background Task in WP 8.1 run more than once

Im trying to implement windows phone 8.1 notification background task.
it is implemented with one bug!
the toast notification message will appear in the action center more than once. sometimes 9times.
here is my code:
public sealed class my_bg_notifier: IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
var deferral = taskInstance.GetDeferral();
bool status = await notificationChecker.check();
if (status)
{
populateNotification(notificationChecker.count);
}
deferral.Complete();
}
}
I tried to debug so I put a breakpoint over the line status.
and I was surprised that it is called more than once and that is why my notification will pop-up more than one time.
and the message that is showed from the debugger breakpoint clearly states that there are multiple threads doing the same job simultaneously.
so i thought to prevent running the method by more than one thread by using a boolean flag as follow:
public sealed class my_bg_notifier: IBackgroundTask
{
private static bool isNotBusy = true;
public async void Run(IBackgroundTaskInstance taskInstance)
{
if (isNotBusy)
{
isNotBusy = false;
var deferral = taskInstance.GetDeferral();
bool status = await notificationChecker.check();
if (status)
{
populateNotification(notificationChecker.count);
}
deferral.Complete();
}
isNotBusy = true;
}
}
but again that didn't work.
my question is :
why would a background task run more than once by multiple thread simultanously.
and How can I block this behavioud? should I use lock keyword?
Okkkkk!!! It was my fault. In my code i registered the background task on each app launch without checking if it is already registered.
So i used code as below to check if my task is registered then no need to register it again.
var taskRegistered = false;
var exampleTaskName = "ExampleBackgroundTask";
foreach (var task in Background.BackgroundTaskRegistration.AllTasks)
{
if (task.Value.Name == exampleTaskName)
{
taskRegistered = true;
break;
}
}
Source: http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh977055.aspx

RequestCycle goes null when using a separate thread

I am using a separate thread to handle the processing of a file. The main thread holds the table to display to the user using a listView, and uses an AjaxSelfUpdatingTimer to refresh the list every second.
The problem is, after processing about 100 lines in my CSV file, I keep getting a no requestCyle exception:
Exception in thread "Thread-12" org.apache.wicket.WicketRuntimeException: No RequestCycle is currently set!
at org.apache.wicket.Component.getRequest(Component.java:1804)
at org.apache.wicket.markup.html.WebPage.dirty(WebPage.java:318)
at org.apache.wicket.Page.dirty(Page.java:249)
at org.apache.wicket.Page.componentStateChanging(Page.java:926)
at org.apache.wicket.Component.addStateChange(Component.java:3528)
at org.apache.wicket.Component.error(Component.java:1225)
at com.wicket.BulkLoadPage$BatchLoaderProcessingThread.processLine(BulkLoadPage.java:806)
at com.wicket.BulkLoadPage$BatchLoaderProcessingThread.run(BulkLoadPage.java:674)
at java.lang.Thread.run(Thread.java:662)
these are my runnable classes the thread calls:
class BatchLoaderProcessingThread implements Runnable
{
#Override
public void run()
{
processLine();
loaderFinished();
}
public void cancelThread()
{
cancelLoaderThread = true;
}
}
class BatchDeleteProcessingThread implements Runnable
{
#Override
public void run()
{
processLine();
deleterFinished();
}
public void cancelThread()
{
cancelDeleterThread = true;
}
}
I don't understand why the requestCycle would just go null.. How can I prevent this from happening?
Edit:
Commenting out feedback message do troubleshoot requestRecycle error, I receive this error:
java.io.IOException: Read error
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:220)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.read1(BufferedReader.java:185)
at java.io.BufferedReader.read(BufferedReader.java:261)
at java.io.BufferedReader.fill(BufferedReader.java:136)
Dec 30 13:14:31 ERROR BulkLoadPage-java.io.IOException: Read error
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at au.com.bytecode.opencsv.CSVReader.getNextLine(CSVReader.java:266)
at au.com.bytecode.opencsv.CSVReader.readNext(CSVReader.java:233)
at com..wicket.BulkLoadPage.processLine(BulkLoadPage.java:547)
at com..wicket.BulkLoadPage.access$0(BulkLoadPage.java:532)
at
com..wicket.BulkLoadPage$BatchLoaderProcessingThread.run(BulkLoadPage.java:1294)
at java.lang.Thread.run(Thread.java:662)
this error only occurs with the larger file as well. All of the lines inside the csv are duplicate only to mimic a large file.. so all lines are the same, and there shouldn't be an error caused directly from the file. Is there something else that I should be looking for that would cause this error from using another thread?
RequestCycle is a thread local singleton. If you're running a process in another thread that really means the RequestCycle singleton doesn't exist in your new thread.
The following example is placed on https://repo.twinstone.org/projects/WISTF/repos/wicket-examples-1.4/browse
The idea is about holding the reference to the current RequestCycle, you cannot call RequestCycle.get() due to the thread local singleton doesn't exist in any other thread. This CustomRequestCycle implementation is ever waiting until the new thread notify its finishing. The counter of loops is just a protection to do not freeze the primary thread if the WaitingRunnable stops working/freezes.
RESULTS oF TESTS:
Check your logs for case 1, the separate thread is finishing very soon, RequestCycle doesn't wait for detaching
http://localhost:8080/wicket-examples14/wait?millis=10
DEBUG - CustomRequestCycle - Waiting until notify: 0
INFO - WaitingRunnableNotifier - Separate thread waiting finished cz.wicketstuff.enteam.wicket.examples14.request.ThreadWaitingPage
INFO - CustomRequestCycle - Notifier returned: Successfully finished
Check your logs for case 2, the separate thread is finishing in time, RequestCycle has to wait for detaching
http://localhost:8080/wicket-examples14/wait?millis=3000
DEBUG - CustomRequestCycle - Waiting until notify: 0
DEBUG - CustomRequestCycle - Waiting until notify: 1
DEBUG - CustomRequestCycle - Waiting until notify: 2
INFO - WaitingRunnableNotifier - Separate thread waiting finished cz.wicketstuff.enteam.wicket.examples14.request.ThreadWaitingPage
INFO - CustomRequestCycle - Notifier returned: Successfully finished
Check your logs for case 3, the separate thread is finishing on time, RequestCycle is already detached
http://localhost:8080/wicket-examples14/wait?millis=10000
DEBUG - CustomRequestCycle - Waiting until notify: 0
DEBUG - CustomRequestCycle - Waiting until notify: 1
DEBUG - CustomRequestCycle - Waiting until notify: 2
DEBUG - CustomRequestCycle - Waiting until notify: 3
DEBUG - CustomRequestCycle - Waiting until notify: 4
DEBUG - CustomRequestCycle - Waiting until notify: 5
DEBUG - CustomRequestCycle - Waiting until notify: 6
DEBUG - CustomRequestCycle - Waiting until notify: 7
INFO - CustomRequestCycle - Notifier returned: null
INFO - WaitingRunnableNotifier - Separate thread waiting finished cz.wicketstuff.enteam.wicket.examples14.request.ThreadWaitingPage
SOURCES:
WicketApplication
#Override
public RequestCycle newRequestCycle(Request request, Response response) {
return new CustomRequestCycle(this, (WebRequest)request, (WebResponse)response);
}
CustomRequestCycle
public class CustomRequestCycle extends WebRequestCycle implements INotifier<String> {
private static final Logger log = LoggerFactory.getLogger(CustomRequestCycle.class);
private long sleepTime = 1000L;
private long maxLoops = 8;
private boolean canDetach = true;
private String notifierResult;
public CustomRequestCycle(WicketApplication application, WebRequest request,
Response response) {
super(application, request, response);
}
public void notifyAny(String payload) {
notifierResult = payload;
canDetach = true;
}
#Override
public void detach() {
long counter = 0;
while(!canDetach && maxLoops > counter) {
log.debug("Waiting until notify: " + counter);
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
// do nothing
}
counter++;
}
log.info("Notifier returned: " + notifierResult);
super.detach();
}
public static CustomRequestCycle get() {
return (CustomRequestCycle)RequestCycle.get();
}
/**
* #return the canDetach
*/
public boolean isCanDetach() {
return canDetach;
}
/**
* #param canDetach the canDetach to set
*/
public void setCanDetach(boolean canDetach) {
this.canDetach = canDetach;
}
}
WaitingRunnableNotifier
public class WaitingRunnableNotifier implements Runnable {
private static final Logger log = LoggerFactory.getLogger(WaitingRunnableNotifier.class);
private final long waitTime;
private RequestCycle requestCycle;
private INotifier<String> notifier;
public WaitingRunnableNotifier(RequestCycle requestCycle, long waitTime, INotifier<String> notifier) {
super();
this.notifier = notifier;
this.requestCycle = requestCycle;
this.waitTime = waitTime;
}
public void run() {
String message = null;
try {
try {
Thread.sleep(waitTime);
} catch (InterruptedException e) {
}
log.info("Separate thread waiting finished " + requestCycle.getResponsePageClass().getCanonicalName());
message = "Successfully finished";
} catch (Exception e) {
log.error("Exception during WaitingRunnableNotifier.run()", e);
message = "Exception: " + e.getMessage();
} finally {
notifier.notifyAny(message);
clean();
}
}
/**
* Clean object references
*/
private void clean() {
requestCycle = null;
notifier = null;
}
}
ThreadWaitingPage is a page with parameter 'millis'. There you can invoke the another thread and wait unitl it is finished.
public class ThreadWaitingPage extends WebPage {
private static final long serialVersionUID = 1L;
private final long millis;
public ThreadWaitingPage(final PageParameters parameters) {
super(parameters);
millis = parameters.getLong("millis");
add(new Label("millis", String.valueOf(millis)));
}
#Override
protected void onInitialize() {
super.onInitialize();
CustomRequestCycle requestCycle = CustomRequestCycle.get();
requestCycle.setCanDetach(false);
new Thread(new WaitingRunnableNotifier(requestCycle, millis, requestCycle)).start();
}
}
Ideally, you shouldn't be creating your own threads, the container should be left to do all that for you. Of course, this means you can't leave bulk processes running in the background between requests.
I've done something similar before (breaking the rule I just mentioned!) and the easiest way is to keep Wicket out of your own threads. If your threads populate a List for example, and your ajax timer callback extracts the records from the list and adds them to the list view.
The problem with list views though is you have to add the parent component to the ajax request target, meaning that the whole list view will be sent back in the ajax response, not just the new entries you've added but all the old ones as well, which would defeat the point of loading them incrementally.
As its only a CSV file, it might be better for you to use a data table, and write a data provider to open the file and read only the records for that request which should be much simpler.
I have temporarily fixed this issue by first loading the lines into a string ArrayList in the main thread and just read from that list inside the thread..
I don't really see any latency issues, so maybe this can be considered a good alternative? If it isn't please let me know, otherwise hopefully this helps someone else some day who struggles with this.
I have also posted my issue here:
http://apache-wicket.1842946.n4.nabble.com/MultiThreading-issues-with-Wicket-td4663325.html#a4663389
and was given some good resource links to review:
Multithreading in wicket:
http://javathoughts.capesugarbird.com/2008/04/spawning-thread-for-lengthy-operation.html
RequestCycle:
http://wicket.apache.org/guide/guide/chapter8.html

Loading Screen not working in Blackberry?

I want to implement a loading screen in blackberry. I try the code from following Support forum link using following code
PleaseWaitPopupScreen.showScreenAndWait(new Runnable() {
public void run() {
//**Segment 1** here i write the code for network call
}
}, "please wait");
// **Segment 2**:Here processing the data get from network call
the problem is the segment 2 works before completing the segment 1. I also try the following code
HorizontalFieldManager popHF = new HorizontalFieldManager();
popHF.add(new LabelField("Pls wait..."));
final PopupScreen waitScreen = new PopupScreen(popHF);
new Thread()
{
public void run()
{
synchronized (UiApplication.getEventLock())
{
UiApplication.getUiApplication().pushScreen(waitScreen);
}
// **Segment 1**Here Some Network Call
synchronized (UiApplication.getEventLock())
{
UiApplication.getUiApplication().popScreen(waitScreen);
}
}
}.start();
// **Segment 2**:Here processing the data get from network call
the same problem arises. Any help will be appreciated.
thanks
Actually it depends on what you're doing in segment 2. If there is no UI actions, then just move segment 2 inside the thread that makes http call. e.g.:
final PopupScreen waitScreen = new PopupScreen(popHF);
new Thread()
{
public void run()
{
synchronized (UiApplication.getEventLock())
{
UiApplication.getUiApplication().pushScreen(waitScreen);
}
// **Segment 1**Here Some Network Call
// **Segment 2**:Here processing the data get from network call
synchronized (UiApplication.getEventLock())
{
UiApplication.getUiApplication().popScreen(waitScreen);
}
}
}.start();
But if there are UI actions inside of segment 2, then call it on UI thread, right after you pop off the wait screen:
final PopupScreen waitScreen = new PopupScreen(popHF);
new Thread()
{
public void run()
{
synchronized (UiApplication.getEventLock())
{
UiApplication.getUiApplication().pushScreen(waitScreen);
}
// **Segment 1**Here Some Network Call
synchronized (UiApplication.getEventLock())
{
UiApplication.getUiApplication().popScreen(waitScreen);
// **Segment 2**:Here processing the data get from network call
}
}
}.start();

Uncaught exception: blocking operation not permitted on event dispatch thread on BlackBerry

I have a HttpConnection thread class. when ı stop httpConnection, I show this messeage.
how should ı stop httpConnection??
Blackberry Output Console:
RuntimeException
blocking operation not permitted on event dispatch thread
net_rim_cldc-10
EventThreadCheck
throwException
0x3434
net_rim_cldc_io_tcp
Protocol
<private>
0x18B8
net_rim_cldc_io_tcp
Protocol
outputStreamClosed
0xB2D
net_rim_cldc_io_tcp
TcpOutputStream
close
0x40BF
net_rim_os-2
ClientProtocol
close
0x154E
CepVizyon-2
Http
cancel
0x174F
CepVizyon-2
Camera
cancel
0x6E7
CepVizyon
ViewCam
close
0xE79
net_rim_cldc-7
Screen
onClose
0x5DAC
net_rim_cldc-7
Screen
keyCharUnhandled
0x5C58
net_rim_cldc-9
MainScreen
keyCharUnhandled
0x23D7
net_rim_cldc-7
Screen
dispatchKeyEvent
0x51DB
net_rim_cldc-7
Screen
processKeyEvent
0x718D
net_rim_cldc-7
UiEngineImpl
processMessage
0x9E3C
net_rim_cldc-4
Application
processNextMessage
0x1073
net_rim_cldc-4
Application
enterEventDispatcher
0x775
CepVizyon-2
CepVizyonMain
main
0x1175
parts of My Connection class:
public abstract class Http extends Thread{
protected HttpConnection httpConnection;
HttpConnectionFactory factory;
protected static Base64 base64;
private boolean cancel = false;
/** bağlantının yapılcağı adres */
protected String url = "";
/** paremetre olarak gönderilecek data */
protected String queryString = "";
...
public void cancel() {
try {
if (httpConnection != null)
httpConnection.close();
if(factory!=null)
factory.cancel();
} catch (IOException ex) {
}
cancel = true;
}
part of my screen class:
public void close() {
super.close();
StaticVar.ActiveCam.cancel();
// CameraListScreen screen = new CameraListScreen();
// UiApplication.getUiApplication().pushScreen(screen);
//
}
and part of Camera Class/*ActiveCam's cancel is here/:
// finishes connection.
public void cancel() {
setConnected(false);
if (mjpeghttp != null) {
mjpeghttp.cancel();
//mjpeghttp.interrupt();
//mjpeghttp = null;
}
}
It looks like your HttpConnection is accessed from a background (non UI) thread which is good. However your UI calls close() directly which may block. You should consider spawning another thread to do the close().
You must work with screen only from event thread
//safely (recommended)
Application.getApplication().invokeLater(new Runnable() {
public void run() {
//your code here
}
});
or
//fast
synchronized(Application.getEventLock()) {
//your code here
}

Resources