My goal is to have an AsyncTask that
can execute multiple times (one task at a time of course)
its current task can be cancelled
can be used by any activity
can execute many different tasks
does not have any problem with screen rotation (or phonecalls etc)
To achieve that i have created the classes shown below. But my experience with (and understanding of) threads is very limited. And since i don't know of any way to debug multiple threads, there is no way (for me) of knowing if this is going to work or not. So what i'm really asking is: Is this code ok?
And since there is no code that it is currently using this, here's an example use for it:
Data2Get d2g = new Data2Get(this, Data2Get.OpCountNumbers);
d2g.setParam("up2Num", String.valueOf(800));
LongOpsRunner.getLongOpsRunner().runOp(d2g);
So, here we go. This is the interface that every activity that wants to execute a long task (operation - op) should implement:
public interface LongOpsActivity {
public void onTaskCompleted(OpResult result);
}
This is a class to enclose any result of any task:
public class OpResult {
public LongOpsActivity forActivity;
public int opType;
public Object result;
public OpResult(LongOpsActivity forActivity, int opType, Object result){
this.forActivity = forActivity;
this.opType = opType;
this.result = result;
}
}
And finally the big part, the singleton async task class:
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import android.os.AsyncTask;
public class LongOpsRunner extends AsyncTask<Void, OpResult, Void> {
public class Data2Get implements Cloneable {
// one id for each operation
public static final int OpCountNumbers = 1;
public static final int OpCountLetters = 2;
public LongOpsActivity forActivity;
public int opType;
private HashMap<String, String> params = new HashMap<String, String>();
public Data2Get(LongOpsActivity forActivity, int opType) {
this.forActivity = forActivity;
this.opType = opType;
}
public void setParam(String key, String value) {
params.put(key, value);
}
public String getParam(String key) {
return params.get(key);
}
public void clearParams() {
params.clear();
}
#Override
protected Object clone() throws CloneNotSupportedException {
// deep clone
Data2Get myClone = (Data2Get) super.clone();
myClone.clearParams();
for (Entry<String, String> entry : params.entrySet()) {
myClone.setParam(new String(entry.getKey()), new String(entry.getValue()));
}
return myClone;
}
}
private class IntermediateResult extends OpResult {
public IntermediateResult(LongOpsActivity forActivity, int opType, Object result) {
super(forActivity, opType, result);
}
}
// not really needed
private class FinalResult extends OpResult {
public FinalResult(LongOpsActivity forActivity, int opType, Object result) {
super(forActivity, opType, result);
}
}
private final ReentrantLock lock = new ReentrantLock();
private final Condition executeOp = lock.newCondition();
private volatile boolean finished = false;
private volatile boolean waiting = true;
private volatile boolean shouldCancel = false;
private volatile boolean activityHasBeenNotified = true;
private Data2Get startingOpParams = null;
private Data2Get currentOpParams = null;
private FinalResult currentOpResult;
protected Void doInBackground(Void... nothing) {
try {
lock.lockInterruptibly();
do {
waiting = true;
while (waiting) {
executeOp.await();
}
shouldCancel = false;
activityHasBeenNotified = false;
boolean opCancelled = false;
try {
currentOpParams = (Data2Get) startingOpParams.clone();
} catch (CloneNotSupportedException cns) {
// do nothing
}
switch (currentOpParams.opType) {
case Data2Get.OpCountNumbers:
int numberCounter = 0;
int numLoopCount = 0;
while ((!opCancelled) & (numLoopCount <= 5000000)) {
if (!shouldCancel) {
numberCounter = (numberCounter + 1)
% Integer.parseInt(currentOpParams.getParam("up2Num"));
if (numberCounter == 0) {
numLoopCount++;
publishProgress(new IntermediateResult(
currentOpParams.forActivity,
currentOpParams.opType,
"Numbers loop count:" + numLoopCount));
}
} else {
opCancelled = true;
activityHasBeenNotified = true;
}
if (!opCancelled) {
currentOpResult = new FinalResult(
currentOpParams.forActivity,
currentOpParams.opType,
"Numbers loop completed.");
publishProgress(currentOpResult);
}
}
break;
case Data2Get.OpCountLetters:
int letterLoopCount = 0;
char ch = 'a';
while (!opCancelled & (letterLoopCount <= 5000000)) {
if (!shouldCancel) {
ch++;
if (Character.toString(ch).equals(currentOpParams.getParam("up2Letter"))) {
ch = 'a';
letterLoopCount++;
publishProgress(new IntermediateResult(
currentOpParams.forActivity,
currentOpParams.opType,
"Letters loop count:" + letterLoopCount));
}
} else {
opCancelled = true;
activityHasBeenNotified = true;
}
if (!opCancelled) {
currentOpResult = new FinalResult(
currentOpParams.forActivity,
currentOpParams.opType,
"Letters loop completed.");
publishProgress(currentOpResult);
}
}
break;
default:
}
} while (!finished);
lock.unlock();
} catch (InterruptedException e) {
// do nothing
}
return null;
}
public void cancelCurrentOp() {
shouldCancel = true;
}
#Override
protected void onProgressUpdate(OpResult... res) {
OpResult result = res[0];
if (result instanceof IntermediateResult) {
// normal progress update
// use result.forActivity to show something in the activity
} else {
notifyActivityOpCompleted(result);
}
}
public boolean currentOpIsFinished() {
return waiting;
}
public void runOp(Data2Get d2g) {
// Call this to run an operation
// Should check first currentOpIsFinished() most of the times
startingOpParams = d2g;
waiting = false;
executeOp.signal();
}
public void terminateAsyncTask() {
// The task will only finish when we call this method
finished = true;
lock.unlock(); // won't this throw an exception?
}
protected void onCancelled() {
// Make sure we clean up if the task is killed
terminateAsyncTask();
}
// if phone is rotated, use setActivity(null) inside
// onRetainNonConfigurationInstance()
// and setActivity(this) inside the constructor
// and all that only if there is an operation still running
public void setActivity(LongOpsActivity activity) {
currentOpParams.forActivity = activity;
if (currentOpIsFinished() & (!activityHasBeenNotified)) {
notifyActivityOpCompleted(currentOpResult);
}
}
private void notifyActivityOpCompleted(OpResult result) {
if (currentOpParams.forActivity != null) {
currentOpParams.forActivity.onTaskCompleted(result);
activityHasBeenNotified = true;
}
}
private static LongOpsRunner ref;
private LongOpsRunner() {
this.execute();
}
public static synchronized LongOpsRunner getLongOpsRunner() {
if (ref == null)
ref = new LongOpsRunner();
return ref;
}
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}
I hope someone helps with making this work, as it would be very useful not only for me, but many other people out there. Thank you.
Try Loaders. I switched from simple AsyncTasks to AsyncTaskLoaders and they solve lots of problems. If you implement a Loader as a standalone class, it would meet all of your requirements, especially when it comes to rotation which is the biggest issue with old AsyncTask.
Related
In my program a number of values are stored on the server.
I read these data using of the AsyncTask class from the server.
This is my code:
public class TestActivity extends AppCompatActivity {
private static List<String> mPackName;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPackName = new ArrayList<>();
try {
boolean check = new GetDataAsyncTask().execute("1234567").get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
e.printStackTrace();
e.printStackTrace();
}
}
private class GetDataAsyncTask extends AsyncTask<String, Void, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
final String mCode = params[0];
APIGettingPosts apiGettingPosts = new APIGettingPosts(TestActivity.this, "get_off_code.php");
apiGettingPosts.getOffCode(new APIGettingPosts.OnOffCodeReceived() {
#Override
public void onReceived(List<Posts> posts) {
if (!(posts == null || posts.isEmpty()))
for (int i = 0; i < posts.size(); ++i) {
mPackName.add(posts.get(i).getTitle());
Log.e("mPackName["+String.valueOf(i)+"]",mPackName.get(i));
}
}
});
Log.e("Size of mPackName: ", String.valueOf(mPackName.size()));
for (int i = 0; i < mPackName.size(); ++i)
if (mCode.equals(mPackName.get(i))) {
Log.e("Is Equal: ", mPackName.get(i));
return true;
}
return false;
}
}
}
The program correctly receives the data from the server and stores it in the mPackName list. At the end of the doInBackground function, the program checks if the input value in the GetDataAsyncTask().execute("1234567") function exists in the mPackName list, returns the true value.
Although the input value of the GetDataAsyncTask().execute("1234567") function is in the mPackNamelist, the program returns the false value.
The Log cat output is as follows:
08-28/com.green E/Size of mPackName:: 0
08-28/com.green E/mPackName[0]: 1234567
08-28/com.green E/mPackName[1]: QAZXSWE
08-28/com.green E/mPackName[2]: QWERTYU
The size of the mPackName list is also zero in Log cat , although it has three values {'1234567','QAZXSWE','QWERTYU'}.
The question is: How do I search '1234567' value in the mPackName list to return the true value in check = new GetDataAsyncTask().execute("1234567").get();
code?
Edited Answer
Looks like you even don't need AsyncTask as getOffCode method already runs in background thread.
Remove GetDataAsyncTask class and create a method like below.
private void search(final SearchCallback callback) {
APIGettingPosts apiGettingPosts = new APIGettingPosts(TestActivity.this, "get_off_code.php");
apiGettingPosts.getOffCode(new APIGettingPosts.OnOffCodeReceived() {
#Override
public void onReceived(List<Posts> posts) {
if (!(posts == null || posts.isEmpty())) {
for (int i = 0; i < posts.size(); ++i) {
mPackName.add(posts.get(i).getTitle());
Log.e("mPackName[" + String.valueOf(i) + "]", mPackName.get(i));
if (mCode.equals(mPackName.get(i))) {
callback.onSearchFound(true);
break;
}
}
}
callback.onSearchFound(false);
}
});
}
public interface SearchCallback{
void onSearchFound(boolean success);
}
Then call from onCreate method like below
search(new SearchCallback(){
#Override
public void onSearchFound(boolean success) {
}
});
Try placing a switch in the onPostExecute() method.
EG.
...
private class GetDataAsyncTask extends AsyncTask<String, Void, Boolean> {
#Override
void onPostExecute(Object o){
handleResults()
}
...
void handleResults(){
// Insert your check here
}
I have custom ImageView for animated GIF image. i want to show GIF image, I tried but in this case it is contain url in Async instead I want to show GIF image from raw folder without using Glide. Anyone have any idea how to show image? Please guyz help to solve this problem!!!
I tried this for set raw file
new GifStaticData() {
#Override
protected void onPostExecute(Resource drawable) {
super.onPostExecute(drawable);
gifImageView.setImageResource(R.raw.earth_tilt_animation);
// Log.d(TAG, "GIF width is " + gifImageView.getGifWidth());
// Log.d(TAG, "GIF height is " + gifImageView.getGifHeight());
}
}.execute(R.raw.earth_tilt_animation);
GifStaticData.java
public class GifStaticData extends AsyncTask<Resource, Void, Resource> {
private static final String TAG = "GifDataDownloader";
#Override protected Resource doInBackground(final Resource... params) {
final Resource gifUrl = params[0];
if (gifUrl == null)
return null;
try {
// return ByteArrayHttpClient.get(gifUrl);
return gifUrl;
} catch (OutOfMemoryError e) {
Log.e(TAG, "GifDecode OOM: " + gifUrl, e);
return null;
}
}
}
GifImageView.java
public class GifImageView extends ImageView implements Runnable {
private static final String TAG = "GifDecoderView";
private GifDecoder gifDecoder;
private Bitmap tmpBitmap;
private final Handler handler = new Handler(Looper.getMainLooper());
private boolean animating;
private boolean shouldClear;
private Thread animationThread;
private OnFrameAvailable frameCallback = null;
private long framesDisplayDuration = -1L;
private OnAnimationStop animationStopCallback = null;
private final Runnable updateResults = new Runnable() {
#Override
public void run() {
if (tmpBitmap != null && !tmpBitmap.isRecycled()) {
setImageBitmap(tmpBitmap);
}
}
};
private final Runnable cleanupRunnable = new Runnable() {
#Override
public void run() {
tmpBitmap = null;
gifDecoder = null;
animationThread = null;
shouldClear = false;
}
};
public GifImageView(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public GifImageView(final Context context) {
super(context);
}
public void setBytes(final byte[] bytes) {
gifDecoder = new GifDecoder();
try {
gifDecoder.read(bytes);
gifDecoder.advance();
} catch (final OutOfMemoryError e) {
gifDecoder = null;
Log.e(TAG, e.getMessage(), e);
return;
}
if (canStart()) {
animationThread = new Thread(this);
animationThread.start();
}
}
public long getFramesDisplayDuration() {
return framesDisplayDuration;
}
/**
* Sets custom display duration in milliseconds for the all frames. Should be called before {#link
* #startAnimation()}
*
* #param framesDisplayDuration Duration in milliseconds. Default value = -1, this property will
* be ignored and default delay from gif file will be used.
*/
public void setFramesDisplayDuration(long framesDisplayDuration) {
this.framesDisplayDuration = framesDisplayDuration;
}
public void startAnimation() {
animating = true;
if (canStart()) {
animationThread = new Thread(this);
animationThread.start();
}
}
public boolean isAnimating() {
return animating;
}
public void stopAnimation() {
animating = false;
if (animationThread != null) {
animationThread.interrupt();
animationThread = null;
}
}
public void clear() {
animating = false;
shouldClear = true;
stopAnimation();
handler.post(cleanupRunnable);
}
private boolean canStart() {
return animating && gifDecoder != null && animationThread == null;
}
public int getGifWidth() {
return gifDecoder.getWidth();
}
public int getGifHeight() {
return gifDecoder.getHeight();
}
#Override public void run() {
if (shouldClear) {
handler.post(cleanupRunnable);
return;
}
final int n = gifDecoder.getFrameCount();
do {
for (int i = 0; i < n; i++) {
if (!animating) {
break;
}
//milliseconds spent on frame decode
long frameDecodeTime = 0;
try {
long before = System.nanoTime();
tmpBitmap = gifDecoder.getNextFrame();
frameDecodeTime = (System.nanoTime() - before) / 1000000;
if (frameCallback != null) {
tmpBitmap = frameCallback.onFrameAvailable(tmpBitmap);
}
if (!animating) {
break;
}
handler.post(updateResults);
} catch (final ArrayIndexOutOfBoundsException | IllegalArgumentException e) {
Log.w(TAG, e);
}
if (!animating) {
break;
}
gifDecoder.advance();
try {
int delay = gifDecoder.getNextDelay();
// Sleep for frame duration minus time already spent on frame decode
// Actually we need next frame decode duration here,
// but I use previous frame time to make code more readable
delay -= frameDecodeTime;
if (delay > 0) {
Thread.sleep(framesDisplayDuration > 0 ? framesDisplayDuration : delay);
}
} catch (final Exception e) {
// suppress any exception
// it can be InterruptedException or IllegalArgumentException
}
}
} while (animating);
if (animationStopCallback != null) {
animationStopCallback.onAnimationStop();
}
}
public OnFrameAvailable getOnFrameAvailable() {
return frameCallback;
}
public void setOnFrameAvailable(OnFrameAvailable frameProcessor) {
this.frameCallback = frameProcessor;
}
public interface OnFrameAvailable {
Bitmap onFrameAvailable(Bitmap bitmap);
}
public OnAnimationStop getOnAnimationStop() {
return animationStopCallback;
}
public void setOnAnimationStop(OnAnimationStop animationStop) {
this.animationStopCallback = animationStop;
}
public interface OnAnimationStop {
void onAnimationStop();
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
clear();
}
}
I had to play and pause the Gif image Glide - Cannot stop gif onClick- Getting TransitionDrawable instead of Animate/GifDrawable
The idea is to get drawable from view,checking if it is an instance of Gifdrawable and playing and pausing it.(Hoping the gif image is already playing)
Add this In OnClick of GifImageView
Drawable drawable = ((ImageView) v).getDrawable();
if (drawable instanceof GifDrawable) {
GifDrawable animatable = (GifDrawable) drawable;
if (animatable.isRunning()) {
animatable.stop();
} else {
animatable.start();
}
}
I found the solution of above problem using GifMovieView!!!
GifMovieViewer.java
public class GifMovieViewer extends Activity {
private Button btnStart;
private GifMovieView gif1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gif_movie_viewer);
gif1 = (GifMovieView) findViewById(R.id.gif1);
btnStart = (Button) findViewById(R.id.btnStart);
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
gif1.setMovieResource(R.drawable.earth_tilt_animation);
//for pause
// gif1.setPaused(gif1.isPaused());
}
});
}
public void onGifClick(View v) {
GifMovieView gif = (GifMovieView) v;
gif.setPaused(!gif.isPaused());
}
}
Im trying to understand how threading works in Android.
I've created this AsyncTask class, but I still get this warning in my console:
Skipped 295 frames! The application may be doing too much work on its main thread.
LoadAnswersTask class
public class LoadAnswersTask extends AsyncTask<String, Void, ArrayList<MessageItemModel>> {
public interface LoadAnswersEventHandler {
void onLoadFinished(ArrayList<MessageItemModel> answers);
}
protected LoadAnswersEventHandler event;
public LoadAnswersTask(LoadAnswersEventHandler event) {
this.event = event;
}
#Override
protected ArrayList<MessageItemModel> doInBackground(String... params) {
try {
QuestionModel q = QuestionModel.getById(Integer.parseInt(params[0]));
ArrayList<MessageItemModel> items = new ArrayList<>();
for (AnswerModel answer : q.getAnswers()) {
MessageItemModel messageItem = new MessageItemModel();
messageItem.message = answer.getComment();
messageItem.id = answer.getId();
messageItem.parentId = answer.getParentId();
messageItem.gender = answer.getGender();
messageItem.name = answer.getName();
messageItem.reply = (answer.getParentId() > 0);
messageItem.email = answer.getEmail();
messageItem.answer = true;
items.add(messageItem);
}
return items;
} catch (Exception e) {
Log.d(getClass().getName(), "Failed to load question", e);
}
return null;
}
#Override
protected void onPostExecute(ArrayList<MessageItemModel> messageItemModels) {
this.event.onLoadFinished(messageItemModels);
}
}
I also tried this approach, which seems to work - well sort of as I have my items in a Fragment inside a viewpager - and it sometimes didn't load the answers, im suspecting it's because of the WeakReference combined with the viewpager causing event.get() to be null, but i'm really not sure...
private static class LoadAnswersHandler extends Handler {
private WeakReference<LoadAnswersEventHandler> event;
public LoadAnswersHandler(LoadAnswersEventHandler event) {
this.event = new WeakReference<>(event);
}
#Override
public void handleMessage(Message msg) {
if(event.get() != null) {
event.get().onLoadFinished((ArrayList<MessageItemModel>) msg.obj);
}
}
}
private LoadAnswersHandler loadAnswersHandler;
// ...
protected void loadAnswers(final LoadAnswersEventHandler event) {
loadAnswersHandler = new LoadAnswersHandler(event);
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
QuestionModel q = QuestionModel.getById(question.getId());
ArrayList<MessageItemModel> items = new ArrayList<>();
for (AnswerModel answer : q.getAnswers()) {
MessageItemModel messageItem = new MessageItemModel();
messageItem.message = answer.getComment();
messageItem.id = answer.getId();
messageItem.parentId = answer.getParentId();
messageItem.gender = answer.getGender();
messageItem.name = answer.getName();
messageItem.reply = (answer.getParentId() > 0);
messageItem.email = answer.getEmail();
messageItem.answer = true;
items.add(messageItem);
}
loadAnswersHandler.sendMessage(Message.obtain(loadAnswersHandler, UPDATE_UI, items));
} catch (Exception e) {
Log.d(getClass().getName(), "Failed to load question", e);
}
}
});
thread.start();
}
Thanks!
- Simon
I'm trying to create a custom loader which loads an list of data that works fine but now I want to added endless scrolling in the listview. I thought a logical place would be in the loader since almost all the examples I see on the interwebz have a private field in the custom loader which corresponds with the data to be returned to UI and in the deliverResult there is some code like this
#Override
public void deliverResult(T data) {
T oldData = mData;
mData = data;
if (isStarted()) {
// If the loader is currently started, we can immediately deliver a result
super.deliverResult(mData);
}
}
No I thought that mData still contains the previous list [1,2,3,4,5] cause the loader should cache the data to show it instantaneously on configuration changes. And data is the new list [6,7,8,9,10] for instance. I could just add data to mData, mData.add(data) and we are done. Don't have to repeat the code on multiple places or different adapters. But seemingly this doesn't work, everytime you call restartLoader to load the new data the framework creates a new instance of the Loader. Has anyone else run into this problem before? or should I just do the mData.add(data) in the Adapter or somewhere else in the code.
the full implementation of the custom loader which extends ApiResponseLoader which can also be find below:
public class SearchLoader extends ApiResponseLoader {
private SearchType mSearchType;
private int mOffset;
private String mSearchQuery;
public SearchLoader(Context context, SearchType type, int offset, String query) {
super(context);
mSearchType = type;
mOffset = offset;
mSearchQuery = query;
}
#Override
public ApiResponse loadInBackground() {
try {
Map<String, String> parameters = Utils.parametersMap("q:" + mSearchQuery, "offset:" + String.valueOf(mOffset));
return tryLoadInBackground(parameters);
} catch (Exception e) {
setError(e);
return null;
}
}
public ApiResponse tryLoadInBackground(Map<String, String> parameters) throws Exception {
if (mSearchQuery == null) {
throw new NullPointerException("mSearchQuery should not be null");
}
if (mSearchType == SearchType.A) {
return RestAdapter().searchA(parameters);
} else {
return RestAdapter().searchB(parameters);
}
}
}
public abstract class ApiResponseLoader extends AsyncTaskLoader<ApiResponse> {
private final static String TAG = ApiResponseLoader.class.getSimpleName();
private ApiResponse mApiResponse;
private Exception mError;
public ApiResponseLoader(Context context) {
super(context);
}
public abstract ApiResponse tryLoadInBackground(Map<String, String> parameters) throws Exception;
#Override
protected void onStartLoading() {
if (mApiResponse != null) {
deliverResult(mApiResponse);
}
if (takeContentChanged() || mApiResponse == null) {
forceLoad();
}
}
#Override
protected void onForceLoad() {
super.onForceLoad();
}
#Override
protected void onStopLoading() {
cancelLoad();
}
#Override
public void onCanceled(ApiResponse data) {
// Attempt to cancel the current asynchronous load.
super.onCanceled(data);
}
#Override
protected void onReset() {
// Ensure the loader has been stopped.
onStopLoading();
// At this point we can release the resources associated with 'apps' if needed
if (mApiResponse != null) {
mApiResponse = null;
}
}
#Override
public void deliverResult(ApiResponse data) {
if (isReset()) {
// An async query came in while the loader is stopped. We don't need the result
if (data != null) {
onReleaseResources(data);
}
return;
}
if (mApiResponse != null) {
mApiResponse.mMeta = data.mMeta;
mApiResponse.mSampleList.addAll(data.mSampleList);
} else {
mApiResponse = data;
}
if (isStarted()) {
// If the loader is currently started, we can immediately deliver a result
super.deliverResult(mApiResponse);
}
}
public Exception getError() {
return mError;
}
public void setError(Exception mError) {
this.mError = mError;
}
}
I have created a webservice class lokks like below, in with in the "onCreate" method of the service i Have called my webservice which takes around 45 seconds to complete its execution for that time my UI gets black that means it Hangs upto the execution of the web service,
below is the code of my service,
public class productService extends Service
{
private static Context _pctx;
static Vector _productsAll = null;
public static void getInstance(Context context) throws Exception
{
if (_pctx == null)
{
_pctx = context;
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate()
{
try
{
LoadAllProducts();
}
catch (Exception e)
{
e.printStackTrace();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
return START_REDELIVER_INTENT; // 21 sec
}
#Override
public void onDestroy()
{
_productsAll= null;
}
private void LoadAllProducts() throws Exception
{
_productsAll = new Vector();
Exception e = null;
WebResponse myResponse = DataService.GetData("$PR$" , _pctx);
if (Helper.getBoolValueFromString(myResponse.Success))
{
saveMDBData(myResponse.Response);
}
else
{
e = new Exception(myResponse.Response.toString());
}
//cats = null;
if (e != null) {
throw e;
}
}
public static void saveMDBData(StringBuffer pMDBData)
{
Vector Rows;
Vector Cols;
int iRow = 0;
if (pMDBData != null)
{
if (!pMDBData.toString().trim().equals(""))
{
Rows = Helper.getRowsNew(pMDBData);
if (Rows != null)
{
for (iRow = 0; iRow < Rows.size(); iRow++)
{
if (!((String) Rows.elementAt(iRow)).trim().equals(""))
{
Cols = Helper.SplitMultiCharDelimiters((String) Rows.elementAt(iRow), Helper.FIELDDELIMITERS);
assignMDBData(Cols);
}
}
}
}
}
Rows = null;
Cols=null;
}
private static void assignMDBData(Vector pCols)
{
Product myProduct = null;
if (pCols != null)
{
//Create new setting instance
//myProduct = new Product();
myProduct = new Product();
//assign values
myProduct.Id = Helper.getIntValue((String)pCols.elementAt(0));
myProduct.PartNumber = (String)pCols.elementAt(1);
myProduct.Description = (String)pCols.elementAt(2);
myProduct.IdCategory = Helper.getIntValue((String)pCols.elementAt(3));
myProduct.Ideal = Helper.getIntValue((String)pCols.elementAt(4));
myProduct.Taxable = Helper.getBoolValueFromString((String)pCols.elementAt(5));
myProduct.Discountable = Helper.getBoolValueFromString((String)pCols.elementAt(6));
myProduct.LotSize = Helper.getIntValue((String)pCols.elementAt(7));
myProduct.RetailPrice = Helper.getDoubleValue((String)pCols.elementAt(8));
myProduct.ListPrice = Helper.getDoubleValue((String)pCols.elementAt(9));
myProduct.TotalOnHand = Helper.getIntValue((String)pCols.elementAt(10));
myProduct.TotalOnOrder = Helper.getIntValue((String)pCols.elementAt(11));
myProduct.IsPrepack = Helper.getBoolValueFromString((String)pCols.elementAt(12));
//myProduct.Breakdown = (String)pCols.elementAt(13);
myProduct.NoInventory = Helper.getBoolValueFromString((String)pCols.elementAt(13));
myProduct.IsCollection = Helper.getBoolValueFromString((String)pCols.elementAt(14));
myProduct.Followup = Helper.getIntValue((String)pCols.elementAt(15));
myProduct.PctDiscount = Helper.getDoubleValue((String)pCols.elementAt(16));
myProduct.IdGroup = Helper.getIntValue((String)pCols.elementAt(17));
myProduct.Points = Helper.getIntValue((String)pCols.elementAt(18));
myProduct.IsVitamin = Helper.getBoolValueFromString((String)pCols.elementAt(19));
myProduct.PusChange = Helper.getIntValue((String)pCols.elementAt(20));
myProduct.MovedToCloseout = Helper.getDateDataSync((String)pCols.elementAt(21));
myProduct.OnHandDelta = Helper.getIntValue((String)pCols.elementAt(24));
//save processed setting to persistent collection
_productsAll.addElement(myProduct);
//release saved setting in)stance
myProduct = null;
}
}
}
Anyone please help me to sort out the probelm,
I am Stuck Here,
Thanks in Advance!
For Background Services use the AsyncTask which creates background threads so doesn't effect your main UI.
Here is the Code:
public class DownloadData extends AsyncTask<String, String, String> {
#Override
public void onPreExecute() {
// Do Some Task before background thread runs
}
#Override
protected String doInBackground(String... arg0) {
// To Background Task Here
return null;
}
#Override
protected void onProgressUpdate(String... progress) {
// publish progress here
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Do some Task after Execution
}
}
For more details: See this one
http://developer.android.com/reference/android/os/AsyncTask.html