2

ContentProvider이 있는데이 파일은 sqlite 데이터베이스에서 데이터를 가져 와서 Loader을 통해로드합니다. 서버에서 데이터를 다운로드하고 ContentProvider에서 업데이트하려면 AsyncTask을 실행하는 Service으로 업데이트되었습니다. 나는 그것을 확신 할 것이 아니라 분명 희망 :ContentProvider, Loader 및 ProgressBar

  • ListFragment

  • ContentProvider

    Service로 업데이트됩니다, Loader를 통해 ContentProvider에서 데이터를합니다. 내 로컬 SQLite 데이터베이스 내가 응용 프로그램을 실행 처음 비어있을 때

이제, 그들이 현재 Service를 통해 다운로드되고있어, 비록이 이벤트가 없습니다 보여줍니다. 차라리이 순간에 ProgressBar이 표시됩니다 (막대가 아닌 무한 회전 휠). 그러나 데이터베이스에서 결과가 없을 때 ProgressBar을 표시하면 외부 데이터베이스에 레코드가없는 경우에도 서버에서 데이터를 가져온 후에도 해당 데이터베이스에 결과가 표시됩니다. 그래서 :

  • 는 데이터가 ContentProvider까지의 ProgressBar을 보여주고 싶은 ServiceI 에 의해 처음으로 다운로드되면 비어 있지 않은 결과 또는Service 그것이 직업 완료 제공합니다.

  • ContentProvider 아무것도 을 반환 할 때와Service는 I 앱이 "검색 결과를 찾을 수"를 표시하지 싶습니다 작업 (및 가져온 빈 결과) 의 을 완료했다. Service이 여전히 실행되고있는 ListFragment를 통지하거나 TS 작업을 완료되었는지하는 방법 :

내 문제는 아마입니다. 내 말은 - 나는에있는 참조를 저장하지 말아야한다. FragmentService. ContentProviders의 아이디어에 어긋나지? 그래서 방법?

참고 : 어떤 코드 조각이 도움이 될지 잘 모르겠다. 그렇다면 특정 조각을 볼 필요가 있다고 생각하면 의견을 말해주세요. 감사!

답변

1

.

기본적으로 서비스는 다운로드를 시작할 때와 끝내면 응용 프로그램의 모든 구성 요소에 알릴 수 있습니다. 그래서 당신은 두 개의 사용자 정의 액션 문자열을 정의 할 수 있습니다

그런 다음 서비스는 코드의 적절한 지점에서 그들을 방송 한
public static final String ACTION_DOWNLOADSTART = "com.mypackage.intent.ACTION_DOWNLOADSTART"; 
public static final String ACTION_DOWNLOADCOMPLETE = "com.mypackage.intent.ACTION_DOWNLOADCOMPLETE"; 

:

Intent start = new Intent(ACTION_DOWNLOADSTART); 
sendBroadcast(start); 

//...Service does its work 

Intent finish = new Intent(ACTION_DOWNLOADCOMPLETE); 
sendBroadcast(finish); 

당신은 어디서든 BroadcastReceiver 사용하여 응용 프로그램에서이 콜백을 등록 할 수 있습니다 그에 따라 행동하십시오 (즉, ContentProvider의 상태를 확인하고 필요한 경우 진행 상황을 표시/숨기기). 당신이 Service 어떤 주어진 시점에서 실행되고 있는지 확인 할 수 있도록하려는 경우 ServiceonCreate()/onDestroy() 그러나 아마 사이에 아마 (활성화 된 경우

또 다른 일반적인 방법은, 당신이 전환 할 수있는 private static boolean 멤버를 포함하는 것입니다 다른 곳) 및 isRunning()과 같은 접근 자 메서드가 있습니다. 그런 다음 응용 프로그램은 해당 메소드를 호출하여 Service이 실행 중인지 언제든지 확인할 수 있습니다.

+0

대단히 감사합니다. 나중에 오늘 해결책을 찾아 보겠습니다. 그러나 둘 다 매우 유망한 것으로 보입니다. –

+0

아직 작성하지 않았지만 두 번째로 충분하지 않은 것으로 보입니다. 하지만 'BrodcastReceiver'는 내가 찾고있는 것처럼 보입니다. 고마워요! –

+0

LocalBroadcastManager는이 특정 작업에 더 좋습니다 : http://stackoverflow.com/questions/8802157/how-to-use-localbroadcastmanager. 매력처럼 작동합니다 :) –

1

Fragment/ActivityService 사이의 통신 방법은 다양합니다.

그들 중 하나는 ResultReceiver을 사용하고 IntentServiceIntent 엑스트라로 보내고 있습니다.

사용자 지정 수신자 ServiceResultReceiver을 확장하여 ResultReceiver으로 만듭니다.

public class ServiceResultReceiver extends ResultReceiver { 

    private Receiver mReceiver; 

    public ServiceResultReceiver(Handler handler) { 
     super(handler); 
    } 

    public void setReceiver(Receiver receiver) { 
     mReceiver = receiver; 
    } 

    public interface Receiver { 
     public void onReceiveResult(int resultCode, Bundle resultData); 
    } 

    @Override 
    protected void onReceiveResult(int resultCode, Bundle resultData) { 
     if (mReceiver != null) { 
      mReceiver.onReceiveResult(resultCode, resultData); 
     } 
    } 
} 

당신의 Fragment 구현 ServiceResultReceiver.Receiver 인터페이스를 확인합니다. 수신기 을 만들고 Fragment으로 초기화하십시오.리시버를 서비스 및 서비스에 전달하는 대신 리시버를 수신자에게 보내려면 receiver.send()으로 전화하여 리시버로 다시 보내십시오. 이 사용자 정의 방송 한 쌍을 사용하는 것, 어쩌면 정적 부울뿐만 아니라 실행 상태를 보여주기 위해 구현 다시 UI에 간단한 방법을 실제 진행 상황을 게시에 너무 관심이없는 것 때문에

public class MyFragment extends ListFragment implements ServiceResultReceiver.Receiver { 
    private ServiceResultReceiver mReceiver; 
    .... 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     ... 
     mReceiver = new ServiceResultReceiver(new Handler()); 
     mReceiver.setReceiver(this); 
    } 

    public void startMyService() { 
     final Intent intent = new Intent(getActivity(), MyService.class); 
     intent.putExtra("receiver", mReceiver); 
     getActivity().startService(intent); 
    } 

    @Override 
    public void onReceiveResult(int resultCode, Bundle resultData) { 
     // service finished 
    } 
} 

public class MyService extends IntentService { 
    ... 
    @Override 
    protected void onHandleIntent(Intent intent) { 
     // download data and update database 
     .... 
     final ResultReceiver receiver = intent.getParcelableExtra("receiver"); 
     if (receiver != null) { 
      receiver.send(0, null); 
     } 
    } 
} 
+0

'BroadcastReceiver'는 더 쉬운 솔루션처럼 보입니다 + 내 '서비스'는 'IntentService'가 아니지만 (문제가되지 않습니까?), 답변 해 주셔서 감사합니다! –

+1

'IntentService'는 worker 스레드가 이미 구현 된'Service'이며,이 접근법은 google i/o 2010 앱에 도입되었습니다. – biegleux

+1

하나의 제안 된 조정은 서비스가 ServiceResultReceiver에 WeakReference를 보유하도록하는 것입니다. 위에 초안이 작성되었으므로 서비스는 시작한 부분에 대한 참조를 보유하여 작업 기간 동안 가비지 수집을 방지합니다. 이것은 의도적 일 수 있지만, 제 생각에 단순한 예제로 만 수행되었습니다. –